ChuVanKhanh's blog

By ChuVanKhanh, history, 2 years ago, In English

My solution is to count the divisors of (a*b)^2 but a, b <= 1e6. In addition the problem has testcase <= 1e6. Can you help me?

  • Vote: I like it
  • +20
  • Vote: I do not like it

| Write comment?
»
2 years ago, # |
Rev. 12   Vote: I like it +19 Vote: I do not like it

since a and b are both less than 1e6, so I guess you can use sieve.

edit:
precomputation is around O(N) with a tiny constant factor (with euler sieve), as mentioned by ling_luo.
Each query is thus O(log(N)) since we need to iterate through all of the prime factors of the number. Total time complexity then would be O(N+Q*log(N)), which I guess should be well within TL. :D
sorry for my horrible grammar and really, way too many revisions.

  • »
    »
    2 years ago, # ^ |
      Vote: I like it -15 Vote: I do not like it

    i tried using it but it time!

    • »
      »
      »
      2 years ago, # ^ |
        Vote: I like it +10 Vote: I do not like it

      Well the algorithm should get accepted because the time complexity is O(Q log N), maybe your implementation has some problems that made it TLE

»
2 years ago, # |
Rev. 2   Vote: I like it +12 Vote: I do not like it

Obviously a number less than $$$10^6$$$ has at most $$$7$$$ distinct prime divisors. Let's denote $$$d=7$$$.

We can precompute the prime factorizations of numbers ranging from $$$1$$$ to $$$v=10^6$$$ in $$$O(vd)$$$ by Euler sieve.

We can know the factorization of $$$(ab)^2$$$ easily by the factorizations of $$$a$$$ and $$$b$$$.

Then we can know the number of divisors easily, which is sufficent enough to process $$$t=10^6$$$ queries.

Time Complexity: $$$O(vd+td)$$$.

  • »
    »
    2 years ago, # ^ |
    Rev. 2   Vote: I like it +8 Vote: I do not like it

    Rwxy's solution is slightly different: he precomputes the smallest divisor instead of the whole factorization, and recompute the factorization for every query. The complexity, as mentioned by him, is $$$O(v+t\log v)$$$.

    We can optimize it to $$$O(v+td)$$$ by precomputing the smallest divisor $$$p$$$, the power of that $$$k$$$, and the next number(that is the number divided by $$$p^k$$$), that makes it faster.

    • »
      »
      »
      2 years ago, # ^ |
      Rev. 3   Vote: I like it +28 Vote: I do not like it

      thanks for telling me about the optimization!

      • »
        »
        »
        »
        2 years ago, # ^ |
          Vote: I like it +8 Vote: I do not like it

        You're welcome. That also optimizes my solution because $$$v$$$ (your $$$N$$$) can be set up to $$$5\times10^7$$$ and $$$t$$$ (your $$$Q$$$) can be set up to $$$5\times10^6$$$. (assuming around $$$10^8$$$ calculations per second)

        • »
          »
          »
          »
          »
          2 years ago, # ^ |
            Vote: I like it +10 Vote: I do not like it

          How to sieve with the complexity is O(log n)

          • »
            »
            »
            »
            »
            »
            2 years ago, # ^ |
            Rev. 2   Vote: I like it 0 Vote: I do not like it

            What do you mean by sieve? If you mean "recompute the factorization", we repeat dividing the number with the smallest prime divisor until it becomes $$$1$$$.

            • »
              »
              »
              »
              »
              »
              »
              2 years ago, # ^ |
                Vote: I like it 0 Vote: I do not like it
              #include<bits/stdc++.h>
              using namespace std;
              const int N = 1e6+6;
              int prime[N];
              void sieve(){
                  for(int i=1;i<=N;i++)
                  {
                      prime[i]=i;
                  }
                  for(int i=2;i<=sqrt(N);i++)
                  {
                      if(prime[i])
                      {
                          for(int j=i*i;j<=N;j+=i)
                          {
                              if(prime[j]==j) prime[j]=i;
                          }
                      }
                  }
              }
              int main()
              {
                 sieve();
                 short pow[N];
                 int t;
                 cin >> t;
                 while(t--)
                 {
                      vector<int> need;
                      int a, b;
                      long long ans=1;
                      cin >> a >> b;
                      while(a!=1)
                      {
                          int count=0;
                          int flags=prime[a];
                          while(a%flags==0)
                          {
                              count++;
                              a/=flags;
                          }
                          pow[flags] += count;
                          need.push_back(flags);
                      }
                       while(b!=1)
                      {
                          int count=0;
                          int flags=prime[b];
                          while(b%flags==0)
                          {
                              count++;
                              b/=flags;
                          }
                          pow[flags] += count;
                          need.push_back(flags);
                      }
                      for(int i=0;i<need.size();i++)
                      {
                          ans*=(pow[need[i]]*2+1);
                          pow[need[i]]=0;
                      }
                      cout << ans << endl;
                 }
              }
              
              

              Is my solution to this problem need to be optimized anymore? I think my method is so optimal

              • »
                »
                »
                »
                »
                »
                »
                »
                2 years ago, # ^ |
                  Vote: I like it 0 Vote: I do not like it

                It is able to pass the problem, but not optimized. Your solution is $$$O(v\log v+q\log v)$$$, and can be optimized to $$$O(v\log \log v+q\log v)$$$ by replacing if(prime[i]) to if(prime[i]==i).

                If there's something wrong, remind me.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  2 years ago, # ^ |
                    Vote: I like it 0 Vote: I do not like it

                  whether the sieve of Eratosthenes or euler better ? should I replace my sieve with euler for better optimization. Can you show me how to optimize even more! If(a, b <=1e9) what should i do?

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  2 years ago, # ^ |
                    Vote: I like it 0 Vote: I do not like it

                  Euler sieve is $$$O(v)$$$, while Eratosthenes sieve is $$$O(v\log \log v)$$$. About the best solution I can come up with, I mentioned it above. I cannot solve the case where $$$a,b\le 10^9$$$.

»
2 years ago, # |
  Vote: I like it +8 Vote: I do not like it

Why is "The number of solutions for the equation" equal to "Number of divisors of (a*b)^2 " ?

  • »
    »
    2 years ago, # ^ |
    Rev. 2   Vote: I like it +3 Vote: I do not like it

    Rewriting the equation, we get $$$(x - ab)(y - ab) = a^2b^2$$$, and clearly, $$$x$$$ and $$$y$$$ must be positive, so the number of solution is simply $$$d(a^2b^2)$$$. AMC level algebraic manipulation I would say

»
2 years ago, # |
  Vote: I like it +3 Vote: I do not like it

If we have the prime factorization of $$$N$$$, then we can easily calculate the number of factors $$$N^2$$$ as power of each prime will be doubled. So, now the question is to get the prime factorization of $$$a*b$$$. For this we can separately factorize both $$$a$$$ and $$$b$$$ and keep the count of their primes in one $$$map$$$ using sieve.

My implementation using sieve is here .

A similar question can be found here .