HDU4407 Sum

容斥原理:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int N = 1010;
 6 const int Ni = 400010;
 7 bool isprime[Ni];
 8 int id[Ni],tp,pr[30];
 9 int prime[40000],cnt;
10 int ax[N],ac[N];
11 void Prime(){
12     cnt=0;
13     memset(isprime,true,sizeof(isprime));
14     for(int i=2;i<Ni;i++){
15         if(isprime[i]){
16             for(int j=i+i;j<Ni;j+=i)
17                 isprime[j]=false;
18             prime[cnt++]=i;
19         }
20     }
21 }
22 int gcd(int a,int b){
23     if(b==0) return a;
24     return gcd(b,a%b);
25 }
26 long long finds(int x,int n,int p){
27     int t,i,j,num,d,m=1<<n;
28     long long ans=(long long)x*(x+1)/2;
29     for(i=1;i<m;i++) {
30         t=i;j=num=0;d=1;
31         while(t) {
32             if(t&1) {d*=pr[j];num++;}
33             j++;t>>=1;
34         }
35         n=x/d;
36         if(num&1) ans-=(long long )d*(1+n)*n/2;
37         else ans+=(long long) d*(1+n)*n/2;
38     }
39     for(i=0;i<tp;i++) {
40         if(ax[i]>x) continue;
41         if(gcd(ax[i],p)==1) ans-=ax[i];
42         if(gcd(ac[i],p)==1) ans+=ac[i];
43     }
44     return ans;
45 }
46 int pri(int a){
47     if(isprime[a]) {pr[0]=a;return 1;}
48     int k=0,i;
49     for(i=0;i<cnt;i++){
50         if(a%prime[i]==0) pr[k++]=prime[i];
51         while(a%prime[i]==0) a/=prime[i];
52         if(a!=1&&isprime[a]) {pr[k++]=a;return k;}
53     }
54     return k;
55 }
56 int main()
57 {
58     Prime();
59     int n,m,x,y,op,p,cs;
60     scanf("%d",&cs);
61     while(cs--){
62         scanf("%d%d",&n,&m);
63         tp=0; memset(id,-1,sizeof(id));
64         for(int i=0;i<m;i++){
65             scanf("%d",&op);
66             if(op==1){
67                 scanf("%d%d%d",&x,&y,&p);
68                 int num=pri(p);
69                 printf("%I64d\n",finds(y,num,p)-finds(x-1,num,p));
70             }
71             else {
72                 scanf("%d%d",&x,&p);
73                 if(id[x]==-1) {
74                     ax[tp]=x;
75                     ac[tp]=p;
76                     id[x]=tp;
77                     tp++;
78                 }
79                 else
80                     ac[id[x]]=p;
81             }
82         }
83     }
84     return 0;
85 }

 用map写的,其他一样

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <cstring>
 5 using namespace std;
 6 const int Ni = 400010;
 7 bool isprime[Ni];
 8 map<int,int> mp;
 9 int prime[34000],cnt;
10 int factor[30];//素数因子
11 void Prime(){//素数打表
12     cnt=0;
13     memset(isprime,true,sizeof(isprime));
14     for(int i=2;i<Ni;i++){
15         if(isprime[i]){
16             for(int j=i+i;j<Ni;j+=i)
17                 isprime[j]=false;
18             prime[cnt++]=i;
19         }
20     }
21 }
22 int gcd(int a,int b){
23     if(b==0) return a;
24     return gcd(b,a%b);
25 }
26 long long finds(int x,int n,int p){//容斥原理
27     int t,i,j,num,d,m=1<<n;
28     long long ans=(long long)x*(x+1)/2;
29     for(i=1;i<m;i++) {
30         t=i;j=num=0;d=1;
31         while(t) {
32             if(t&1) {d*=factor[j];num++;}
33             j++;t>>=1;
34         }
35         n=x/d;
36         if(num&1) ans-=(long long )d*(1+n)*n/2;
37         else ans+=(long long) d*(1+n)*n/2;
38     }
39     map<int,int>::iterator it;
40     for(it=mp.begin();it!=mp.end();it++) {//处理被改变了的数
41         if(it->first>x) continue;
42         if(gcd(it->first,p)==1) ans-=it->first;
43         if(gcd(it->second,p)==1) ans+=it->second;
44     }
45     return ans;
46 }
47 int pri(int a){//求出a的素数因子
48     if(isprime[a]) {factor[0]=a;return 1;}
49     int k=0,i;
50     for(i=0;i<cnt;i++){
51         if(a%prime[i]==0) factor[k++]=prime[i];
52         while(a%prime[i]==0) a/=prime[i];
53         if(a!=1&&isprime[a]) {factor[k++]=a;return k;}
54     }
55     return k;
56 }
57 int main()
58 {
59     Prime();
60     int n,m,x,y,op,p,cs;
61     scanf("%d",&cs);
62     while(cs--){
63         scanf("%d%d",&n,&m);
64         mp.clear();
65         for(int i=0;i<m;i++){
66             scanf("%d",&op);
67             if(op==1){
68                 scanf("%d%d%d",&x,&y,&p);
69                 int num=pri(p);
70                 printf("%I64d\n",finds(y,num,p)-finds(x-1,num,p));
71             }
72             else {
73                 scanf("%d%d",&x,&p);
74                 mp[x]=p;
75             }
76         }
77     }
78     return 0;
79 }

 

posted @ 2012-09-22 20:41  qijinbiao1  阅读(499)  评论(0编辑  收藏  举报