Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2021
700
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.69 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define MX 100000
  4.  
  5. // Explanation: OleschY
  6.  
  7. // we will calculate for each number, what are its prime factors. Note: We are not interested about
  8. // how often each factor appears. We are happy with knowing whether it appears as prime factor
  9. vector<int> p[100005];
  10.  
  11. // The Input
  12. int a[100005];
  13.  
  14. // This is our dp structure.
  15. // First we will fill dp[0][i]. This is equivalent to go_l from the editorial
  16. // dp[0][i] points to the first element of a[n] which has a common prime factor with a[i]
  17. // In a second dp-step we will create dp[j>0][i]. d[0][i] denotes one step, d[1][i] denotes 2 steps,
  18. // d[2][i] denotes 4 steps from i, and so on. dp[j][i] denotes 1<<j steps from i.
  19. int dp[20][100005];
  20.  
  21. // in the first step of calculating dp[0][i] we will iterate from right to left over a[i]. while
  22. // iterating we will save the next occurance of the prime actor f in nex[f]
  23. int nex[100005];
  24.  
  25. int main()
  26. {
  27.     int n,q;
  28.     scanf("%d%d",&n,&q);
  29.     for (int i=1;i<=n;i++)
  30.     scanf("%d",&a[i]);
  31.  
  32.     // This is a sieve. We fill p[i] with all the prime factors of i
  33.     for (int i=2;i<=MX;i++)
  34.     {
  35.         // p[i] is empty, so i is a prime, so we will mark this as a factor in all numbers p[k*i] with k>=2
  36.         if (p[i].empty())
  37.         {
  38.             // we initialise nex[i] for all i which are prime. It points to the first elkement after the end of a[n]
  39.             nex[i]=n+1;
  40.             for (int j=i;j<=MX;j+=i)
  41.             p[j].push_back(i);
  42.         }
  43.     }
  44.     // we initialise the first value. dp[0][n+1] is out of bounds but has to point to n+1
  45.     // so we can always do multiple jumps and still end up in n+1
  46.     dp[0][n+1]=n+1;
  47.    
  48.     // this is the first step of generating dp[0][i] which is equal to go_l
  49.     for (int i=n;i>0;i--)
  50.     {
  51.         // the segment starting from dp[0][i] can go at most as far as dp[0][i+1]. Then we will have a
  52.         // prime factor collision of a[i+1] and a[dp[0][i+1]]. Thats how we initialise dp[0][i]
  53.         dp[0][i]=dp[0][i+1];
  54.         // Now we need to check for each prime factor of a[i] where its next occurance is.
  55.         for (int j:p[a[i]])
  56.         {
  57.             // to check this we can use our array nex[j].
  58.             // The segment can't go further than the earliest reoccuring primefactor
  59.             dp[0][i]=min(dp[0][i],nex[j]);
  60.             // afterwards we have to update nex[j]. a[i] has the prime factor j.
  61.             // so the next occurence of primefactor j will be a position i
  62.             nex[j]=i;
  63.         }
  64.     }
  65.     // now we can create the exponential jumps for dp[i>0][j].
  66.     // For that we use that e.g. two jumps of length 4 equal one jump of length 8
  67.     // this is manifested in dp[i][j]=dp[i-1][dp[i-1][j]];
  68.     for (int i=1;i<20;i++)
  69.     {
  70.         for (int j=1;j<=n+1;j++)
  71.         dp[i][j]=dp[i-1][dp[i-1][j]];
  72.     }
  73.     // now solving the queries
  74.     while (q--)
  75.     {
  76.         int l,r,ans=0;
  77.         scanf("%d%d",&l,&r);
  78.         // we try jumps starting with the longest jump 1<<19==524288
  79.         // (since MX=100000, i=17 shouldve been enough? its no big performance difference though)
  80.         for (int i=19;i>=0;i--)
  81.         {
  82.             // If we can make a jump and don't overstep r then we make the jump. Else we reduce the jumpsize
  83.             // Note: Each jump only must be checked once. the  "if (dp[i][l]<=r)" is enough
  84.             // we don't need "while(dp[i][l]<=r)" since the jumps are in the form 2**i and we start testing with jumplength>MX/2
  85.             if (dp[i][l]<=r)
  86.             {
  87.                 ans+=(1<<i);
  88.                 l=dp[i][l];
  89.             }
  90.         }
  91.         // Answer. hooray!
  92.         printf("%d\n",ans+1);
  93.     }
  94. }
  95.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement