思路:主要考虑求1-n中与p互质数的和。直接不好求解,反着来!
求1-n中与p不互质的数的和。由于p=p1^e1*p2^e2……
所以有容斥原理来解决。
代码如下:
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<map> 7 #define ll __int64 8 using namespace std; 9 map<int,int>mm; 10 map<int,int>::iterator it; 11 bool f[1000]; 12 int factor[1000],prime[1000],cnt,num,cn; 13 ll an[400001]; 14 void init() 15 { 16 int i,j; 17 cnt=0; 18 for(i=2;i<1000;i++){ 19 if(f[i]==0) prime[cnt++]=i; 20 for(j=0;j<cnt&&i*prime[j]<1000;j++){ 21 f[i*prime[j]]=1; 22 if(i%prime[j]==0) break; 23 } 24 } 25 } 26 void fac(int n) 27 { 28 num=0; 29 for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++){ 30 if(n%prime[i]==0){ 31 factor[num++]=prime[i]; 32 n/=prime[i]; 33 while(n%prime[i]==0) 34 n/=prime[i]; 35 } 36 } 37 if(n>1) factor[num++]=n; 38 } 39 void dfs(ll sum,int nn,int cc) 40 { 41 an[cn++]=cc*sum; 42 for(int i=nn+1;i<num;i++) 43 dfs(sum*factor[i],i,-cc); 44 } 45 int gcd(int a,int b) 46 { 47 if(a<b) swap(a,b); 48 while(b){ 49 int t=a; 50 a=b; 51 b=t%b; 52 } 53 return a; 54 } 55 int main() 56 { 57 int i,j,t,n,m,s,qq,a,b,c,x,y,p; 58 init(); 59 ll ans,ans2,ans1,tt; 60 scanf("%d",&t); 61 while(t--){ 62 scanf("%d%d",&n,&m); 63 mm.clear(); 64 qq=0; 65 for(i=0;i<m;i++){ 66 scanf("%d",&s); 67 if(s==2){ 68 scanf("%d%d",&a,&b); 69 mm[a]=b; 70 } 71 else{ 72 scanf("%d%d%d",&x,&y,&p); 73 if(x>y) swap(x,y); 74 ans=(ll)(x+y)*(y-x+1)/2; 75 cn=0; 76 fac(p); 77 for(j=0;j<num;j++) 78 dfs(factor[j],j,1); 79 for(j=0;j<cn;j++){ 80 if(an[j]>x-1) continue; 81 if(an[j]<0) tt=(x-1)/(-an[j]); 82 else tt=(x-1)/an[j]; 83 ans+=(ll)tt*(tt+1)/2*an[j]; 84 } 85 for(j=0;j<cn;j++){ 86 if(an[j]>y) continue; 87 if(an[j]<0) tt=y/(-an[j]); 88 else tt=y/an[j]; 89 ans-=(ll)tt*(tt+1)/2*an[j]; 90 } 91 for(it=mm.begin();it!=mm.end();it++){ 92 int ff=it->first; 93 int ss=it->second; 94 if(ff<x||ff>y) continue; 95 int t1=gcd(p,ff); 96 int t2=gcd(p,ss); 97 if(t1==1) ans-=ff; 98 if(t2==1) ans+=ss; 99 } 100 printf("%I64d ",ans); 101 } 102 } 103 } 104 return 0; 105 }