XXX is puzzled with the question below: 

1, 2, 3, ..., n (1<=n<=400000) are placed in a line. There are m (1<=m<=1000) operations of two kinds.

Operation 1: among the x-th number to the y-th number (inclusive), get the sum of the numbers which are co-prime with p( 1 <=p <= 400000).
Operation 2: change the x-th number to c( 1 <=c <= 400000).

For each operation, XXX will spend a lot of time to treat it. So he wants to ask you to help him.

容斥原理

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 const int maxn=4e5+5;
 9 
10 inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
11 
12 int ori[1005],cha[1005];
13 int pnum[50],num;
14 
15 int main(){
16     int T;
17     scanf("%d",&T);
18     while(T--){
19         int n,m;
20         scanf("%d%d",&n,&m);
21         int cnt=0;
22         while(m--){
23             int f;
24             scanf("%d",&f);
25             if(f==1){
26                 int x,y,p;
27                 scanf("%d%d%d",&x,&y,&p);
28                 int tmp=p;
29                 num=0;
30                 for(int i=2;i*i<=tmp;++i){
31                     if(!(tmp%i)){
32                         pnum[++num]=i;
33                         tmp/=i;
34                         while(!(tmp%i))tmp/=i;
35                     }
36                 }
37                 if(tmp>1)pnum[++num]=tmp;
38                 ll ans=0;
39                 for(int i=1;i<(1<<num);++i){
40                     int bit=0;
41                     ll mul=1;
42                     for(int j=1;j<=num;++j){
43                         if(i&(1<<(j-1))){
44                             bit++;
45                             mul*=pnum[j];
46                         }
47                     }
48                     ll tmp=y/mul-(x-1)/mul;
49                     ll l=((x-1)/mul+1)*mul,r=y/mul*mul;
50                     tmp=(l+r)*tmp/2;
51                     if(bit%2)ans+=tmp;
52                     else ans-=tmp;
53                 }
54                 ans=(x+y)*(ll)(y-x+1)/2-ans;
55                 for(int i=1;i<=cnt;++i){
56                     if(ori[i]>=x&&ori[i]<=y){
57                         int gcd1=gcd(ori[i],p),gcd2=gcd(cha[i],p);
58                         if(gcd1==1&&gcd2>1)ans-=ori[i];
59                         else if(gcd1>1&&gcd2==1)ans+=cha[i];
60                         else if(gcd1==1&&gcd2==1)ans=ans-ori[i]+cha[i];
61                     }
62                 }
63                 printf("%lld\n",ans);
64             }
65             else{
66                 int x,c;
67                 scanf("%d%d",&x,&c);
68                 bool f=1;
69                 for(int i=1;i<=cnt;++i){
70                     if(ori[i]==x){
71                         cha[i]=c;
72                         f=0;
73                         break;
74                     }
75                 }
76                 if(f){
77                     ++cnt;
78                     ori[cnt]=x;
79                     cha[cnt]=c;
80                 }
81             }
82         }
83     }
84     return 0;
85 }
View Code