zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    hdu 1823 Luck and Love 二维线段树
    UVA 12299 RMQ with Shifts 线段树
    HDU 4578 Transformation 线段树
    FZU 2105 Digits Count 线段树
    UVA 1513 Movie collection 树状数组
    UVA 1292 Strategic game 树形DP
    【ACM】hdu_zs2_1003_Problem C_201308031012
    qsort快速排序
    【ACM】nyoj_7_街区最短路径问题_201308051737
    【ACM】nyoj_540_奇怪的排序_201308050951
  • 原文地址:https://www.cnblogs.com/qijinbiao/p/2698404.html
Copyright © 2011-2022 走看看