Блог пользователя TARS

Автор TARS, история, 4 года назад, По-английски

I've tried to solve this using sieve and prime factorization but I got TLE for some cases. Here is the CSES problem:) (https://cses.fi/problemset/task/1713/)

Here is my solution)

I need a more efficient approach.

  • Проголосовать: нравится
  • +16
  • Проголосовать: не нравится

»
4 года назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Why do you need the primes? You just need to precalculate using sieve. Anyway, this problem is pretty well known. You can easily find the solution on the internet.

»
4 года назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

You can solve this task using sieve in O(x log log x + N log x). You don't need different approach here.

If you are very interested, there is a method how to calculate all the divisors of the number in... well, something like O(n^(1/4)*log^2) using this algorithm.

But this task can be esily solved with sieve.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится -8 Проголосовать: не нравится

    Well, this works only for small factors, large primes factors won't work efficiently.

»
4 года назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Naive O(NsqrtX) should work since X=10^6 and N=10^5 (so 10^8 operations). I'm calling sqrtX naive because it's pretty well known.

At least, I did that and got AC, so it should probably work for you.

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    When I saw constraints, I also thought about sqrt implementation [but it didn't work for me for some cases though.] Here is my sqrt(x) solution. (https://ideone.com/XRfRBn)

    • »
      »
      »
      4 года назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      I think speeding up cin/cout (with ios_base::sync_with_stdio(false)) and avoiding unneeded long longs should be enough to AC.

»
4 года назад, # |
Rev. 4   Проголосовать: нравится +15 Проголосовать: не нравится

There is also a very well known algotithm to compute divisors of all numbers $$$\le x$$$ in $$$O(x\log x)$$$.

for(int i=1;i<=x;i++){
    for(int j=i;j<=x;j+=i){
        divisors[j].push_back(i);
    }
}

This is $$$O(xH_x)$$$, which is well known to be $$$O(x\log x)$$$. This not only computes the number of divisors, but also stores all of them for all numbers.

Just in case you don't know $$$H_x$$$ you can read this

  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится

    I don't understand how that turns out to be $$$O(xH_x)$$$, shouldn't it be

    for (int i = 1; i <= x; i++)
    {
        for (int j = i; j <= x; j += i)
        {
            divisors[j].push_back(i);
        }
    }
    

    I.e., we increment $$$j$$$ by $$$i$$$, not by $$$1$$$.

    Otherwise the complexity seems quadratic to me.

    • »
      »
      »
      4 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      You are correct. I really need to stop making mistakes. Corrected in OP.

»
4 года назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

I used Pollard Rho's factoring with Miller Rabin primality test. I took the factoring from one of dacin21's submissions.

Submission

»
4 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
#define vector<int> vi;
vi v(N+1,0);
void factorize (vi v){
	for(int i=1;i<=N;i++)
		for(int j=i;j<=N;j+=i){
			v[j]+=1;
		}
	return v;
}

I used this to count the number of divisors for Atcoder Beginner Contest. Worked for me this is a similar to seive so i guess runtime is same as seive