- Let f(n)be the number of operations aggregated from the outer loop,
- Let g(n)be the number of operations aggregated at the level of the first inner loop.
- Let h(n)be the number of operations performed at the level of the third (most inner) loop.
Looking at the most inner loop
for (int k=0; k<j; k++)
   printf("*");
We can say that h(j) = j.
Now, as j varies from i to i*i, the following values of i satisfy i%j = 0, i.e. i is a multiple of j:
j = 1.i
j = 2.i
j = 3.i
...
j = (i-1).i
So
g(i) = sum(j=i, j<i^2, h(j) if j%i=0, else 0)
     = h(i) + h(2.i) + ... + h((i-1).i)
     = i + 2.i + ... + (i-1).i
     = i.(1 + 2 + ... + i-1) = i.i.(i-1)/2
     = 0.5i^3   // dropped the term -0.5i^2 dominated by i^3 as i -> +Inf
=> f(n) = sum(i=0, i<n, g(i))
        = sum(i=0, i<n, 0.5i^3)
       <= sum(i=0, i<n, 0.5n^3)
       <= 0.5n^4
=> f(n) = O(n^4)