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 }
  • 相关阅读:
    Lookup Method
    ReLocated Record in Grid
    Call Form By FormString
    Send Mail
    十大已亡或正在灭亡的电脑技术
    一个程序员的内心自白摘录
    数据库中null和''具体的区别
    gridview 横向显示
    Exchange2007获取OWA邮箱容量的代码
    owa实现清空邮箱的代码
  • 原文地址:https://www.cnblogs.com/qijinbiao/p/2698404.html
Copyright © 2011-2022 走看看