zoukankan      html  css  js  c++  java
  • 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 *
    ",x,y,p);
     90     if(cnt%2)ans=-ans;
     91     //printf("**%lld
    ",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
    ",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 }
  • 相关阅读:
    Vue 备
    mac 下如何建立vue-cli项目
    24,25-request对象
    nodejs 备忘
    nodejs中mysql断线重连
    创建node.js,blog
    Mac 升级node与npm
    js 弹出层,以及在javascript里定义层样式
    js 光标选中 操作
    js 捕获型事件
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4365302.html
Copyright © 2011-2022 走看看