hdu 4407 容斥原理
题意:
1 //一组数据 3 3 //数字为1-3,3次运算 2 2 3 //将2号位变成3 1 1 3 4 //计算1-3号位上与4互质的数的和 1 2 3 6
好题,需要重复练习
1 //1008 2 #include<stdio.h> 3 #include<iostream> 4 #include<map> 5 #include<set> 6 #include<algorithm> 7 #include<string.h> 8 #include<stdlib.h> 9 using namespace std; 10 11 int gcd(int a,int b) 12 { 13 if(b==0)return a; 14 return gcd(b,a%b); 15 } 16 17 long long sum1(int x,int y,int p)//求区间[x,y]中p的倍数的和 18 { 19 if(p>y)return 0; 20 int t1=x/p; 21 int t2=y/p; 22 if(t1*p<x)t1++; 23 if(t2<t1)return 0; 24 long long sum=0; 25 sum=(long long)p*(t1+t2)*(t2-t1+1)/2; 26 return sum; 27 } 28 29 const int MAXN=400000; 30 int prime[MAXN+1]; 31 int getPrime()//得到小于等于MAXN的素数,prime[0]存放的是个数 32 { 33 memset(prime,0,sizeof(prime)); 34 for(int i=2;i<=MAXN;i++) 35 { 36 if(!prime[i]) prime[++prime[0]]=i; 37 for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++) 38 { 39 prime[prime[j]*i]=1; 40 if(i%prime[j]==0) break; 41 } 42 } 43 return prime[0]; 44 } 45 long long factor[100][2]; 46 int facCnt; 47 int getFactors(long long x)//把x进行素数分解 48 { 49 facCnt=0; 50 long long tmp=x; 51 for(int i=1;prime[i]<=tmp/prime[i];i++) 52 { 53 factor[facCnt][1]=0; 54 if(tmp%prime[i]==0) 55 { 56 factor[facCnt][0]=prime[i]; 57 while(tmp%prime[i]==0) 58 { 59 factor[facCnt][1]++; 60 tmp/=prime[i]; 61 } 62 facCnt++; 63 } 64 } 65 if(tmp!=1) 66 { 67 factor[facCnt][0]=tmp; 68 factor[facCnt++][1]=1; 69 } 70 return facCnt; 71 } 72 73 long long SS(int s,int x,int y) 74 //求[x,y]之间是素因子倍数的和。素因子的状态是s,0表示没有这个素因子, 75 //1表示有。容斥原理。先不管加减,先奇数加,偶数加,最后按照正负去调整就好了。 76 { 77 long long ans=0; 78 int cnt=0; 79 int p=1; 80 for(int i=0;i<facCnt;i++) 81 { 82 if(s&(1<<i)) 83 { 84 cnt++; 85 p*=factor[i][0]; //由于类似2,3,会导致在计算6时重复计算,所以所有素因子都要计算一遍 86 } 87 } 88 ans=sum1(x,y,p); 89 //printf("%d %d * %d *\n",x,y,p); 90 if(cnt%2)ans=-ans; 91 //printf("**%lld\n",ans); 92 return ans; 93 } 94 95 long long solve1(int x,int y,int p)//求[x,y]之间和p不互素的数的和 96 { 97 getFactors(p); 98 long long ans=0; 99 for(int i=1;i<(1<<facCnt);i++) 100 ans+=SS(i,x,y); 101 if(ans<0)ans=-ans; 102 return ans; 103 } 104 map<int,int>mp; 105 map<int,int>::iterator it; 106 107 long long query(int x,int y,int p)//查询。改变被修改了的就可以了 108 { 109 long long ans=(long long)(x+y)*(y-x+1)/2; //原本的和 110 long long temp=solve1(x,y,p); //与p不互质的数的和 111 ans-=temp; 112 for(it=mp.begin();it!=mp.end();it++) 113 { 114 int t1=it->first; 115 if(t1<x||t1>y)continue; 116 int t2=it->second; 117 if(gcd(t1,p)==1)ans-=t1;//本来互素的要减掉 118 if(gcd(t2,p)==1)ans+=t2;//修改后互素的要加上 119 } 120 return ans; 121 } 122 int main() 123 { 124 getPrime(); 125 #ifndef ONLINE_JUDGE 126 freopen("1.in","r",stdin); 127 #endif 128 int T; 129 int n,m; 130 int x,y,p; 131 int t; 132 scanf("%d",&T); 133 while(T--) 134 { 135 scanf("%d%d",&n,&m); 136 mp.clear(); 137 while(m--) 138 { 139 scanf("%d",&t); 140 if(t==1) 141 { 142 scanf("%d%d%d",&x,&y,&p); 143 if(x>y)swap(x,y); 144 printf("%I64d\n",query(x,y,p)); 145 } 146 else 147 { 148 scanf("%d%d",&x,&p); 149 mp[x]=p; 150 } 151 } 152 } 153 return 0; 154 }