询问 x ~ y 与 p 互素的数字的和是多少。

因为询问+修改只有 1000 次,所以可以枚举修改的值。

1~n 有多少个数与p互素:将p拆成素因子,容斥定理搞一搞。

给出比赛时候的简陋代码。

View Code
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<climits>
  6 #include<cstdlib>
  7 #include<cmath>
  8 using namespace std;
  9 #define N 1010
 10 #define M 400010
 11 typedef __int64 ll;
 12 int prim[710], pr[710], top = 0, yi[20], tail;
 13 int id[M];
 14 struct node {
 15     int x, c;
 16 }qu[N];
 17 void S(){
 18     memset(prim,0,sizeof(prim));
 19     prim[1]=prim[0]=1;
 20     for(int i=2;i<=700;i++)
 21         if(!prim[i]){
 22             pr[top++] = i;
 23             for(int j=i*2;j<=700;j+=i)
 24                 prim[j]=1;
 25         }
 26 }
 27 int pri(int x) {
 28     int m = sqrt(1.0 * x), k = 0;
 29     for (int i = 0; i < top && pr[i] <= m; ++i) {
 30         if (x % pr[i] == 0) {
 31             x /= pr[i];
 32             yi[k++] = pr[i];
 33             while (x % pr[i] == 0) x /= pr[i];
 34         }
 35     }
 36     if (x != 1) yi[k++] = x;
 37     return k;
 38 }
 39 int Gcd(int a, int b)
 40 {
 41     if(b==0) return a;
 42     return Gcd(b,a%b);
 43 }
 44 ll find(int x, int n, int p) {
 45     ll ans = (ll)x*(x+1)/2;
 46     for (int i = 1; i < 1<<n; ++i) {
 47         int t = i, k = 0, num = 0;
 48         ll temp = 1;
 49         while (t) {
 50             if (t&1) {
 51                 num++;
 52                 temp *= yi[k];
 53             }
 54             t >>= 1;
 55             ++k;
 56         }
 57         ll tb = ll(x)/temp;
 58         if (num&1) ans -= temp*(1+tb)*tb/2;
 59         else ans += temp*(1+tb)*tb/2;
 60     }
 61     for (int i = 0; i < tail; ++i) {
 62         if (qu[i].x > x) continue;
 63         int t2 = Gcd(qu[i].x, p);
 64         int t1 = Gcd(qu[i].c, p);
 65         if (t2 == 1) ans -= qu[i].x;
 66         if (t1 == 1) ans += qu[i].c;
 67     }
 68     return ans;
 69 }
 70 int main() {
 71     S();
 72     int T, n, m, f, x, y, c, p;
 73     scanf("%d", &T);
 74     while (T--) {
 75         memset(id, -1, sizeof(id));
 76         tail = 0;
 77         scanf("%d%d", &n, &m);
 78         while (m--) {
 79             scanf("%d", &f);
 80             if (f == 2) {
 81                 scanf("%d%d", &x, &c);
 82                 if (id[x] == -1) {
 83                     id[x] = tail;
 84                     qu[tail].x = x;
 85                     qu[tail].c = c;
 86                     tail++;
 87                 }
 88                 else {
 89                     qu[id[x]].x = x;
 90                     qu[id[x]].c = c;
 91                 }
 92             }
 93             else {
 94                 scanf("%d%d%d", &x, &y, &p);
 95                 int n = pri(p);
 96                 printf("%I64d\n", find(y, n, p)-find(x-1, n, p));
 97             }
 98         }
 99     }
100     return 0;
101 }

相关文章: