hdu 4407 容斥定理
2013-02-06 02:02
309 查看
题意:有一个元素为 1~n 的数列{An},有2种操作(1000次):
1、求某段区间 [a,b] 中与 p 互质的数的和。
2、将数列中某个位置元素的值改变。
思路:acm数学方面实在很差~学习ing~看解题报告A的
容斥定理,看《组合数学》时看到过,但是从来没用过,求第x个数到第y个数中与p互素的数的和。
p=p1^a1 * p2^a2 * p3^a3 * ……其中p1,p2,p3……是n的素因子,ai是pi的指数。
求出 1~y的与p互素的数的和 减去 1~x的与p互素的数的和。
只要是pi的倍数的,则不可能与p互素。所以例如30=2*3*5;那么
1~y的与30互素的数的和=y*(y+1)-2的倍数和-3的倍数和-5的倍数和+2*3的倍数和+3*5的倍数和+2*5的倍数和-2*3*5的倍数和+(改变量)。
(改变量):如果改变的的大于y则无视,否则,如果 改变后的值 与p互素,则+改变后的值
如果 改变前的值 与p互素,则-改变前的值。
感觉在处理容斥定理这一部分的代码写的很好。
View Code
1、求某段区间 [a,b] 中与 p 互质的数的和。
2、将数列中某个位置元素的值改变。
思路:acm数学方面实在很差~学习ing~看解题报告A的
容斥定理,看《组合数学》时看到过,但是从来没用过,求第x个数到第y个数中与p互素的数的和。
p=p1^a1 * p2^a2 * p3^a3 * ……其中p1,p2,p3……是n的素因子,ai是pi的指数。
求出 1~y的与p互素的数的和 减去 1~x的与p互素的数的和。
只要是pi的倍数的,则不可能与p互素。所以例如30=2*3*5;那么
1~y的与30互素的数的和=y*(y+1)-2的倍数和-3的倍数和-5的倍数和+2*3的倍数和+3*5的倍数和+2*5的倍数和-2*3*5的倍数和+(改变量)。
(改变量):如果改变的的大于y则无视,否则,如果 改变后的值 与p互素,则+改变后的值
如果 改变前的值 与p互素,则-改变前的值。
感觉在处理容斥定理这一部分的代码写的很好。
View Code
#include <map> #include <string.h> #include <stdio.h> #include <iostream> using namespace std; const int N=400005; int factor[30];//存因子的数组 bool isPrime ;//判断是否是素数表 int prime ,cnt;//存素数 map<int,int>M;//存第2种操作,改变的值 int gcd(int a,int b){//最大公约数 while(a=a%b)a^=b^=a^=b; return b; } void IsPrime(){//筛选法打素数表 int i,j; cnt=0; memset(isPrime,1,sizeof(isPrime)); for(i=2;i<N;i++){ if(isPrime[i]){ for(j=i+i;j<N;j+=i) isPrime[j]=0; prime[cnt++]=i; } } } int getPrime(int p){//求p的所有素数因子 if(isPrime[p]) {factor[0]=p;return 1;} int i,k=0; for(i=0;i<cnt;i++){ if(p%prime[i]==0) factor[k++]=prime[i]; while(p%prime[i]==0) p/=prime[i]; if(p!=1&&isPrime[p]) {factor[k++]=p;return k;} } return k; } long long find(int x,int n,int p){//find()函数求在1~x内与p互素的个数 int i,j,t,d;//j是第几个因子的下角标,t是临时 int m=1<<n;//p有n个素因子 int num;//记录第几次,决定加还是减 例如,30=2*3*5,-2-3-5 +2*3+3*5+2*5 -2*3*5 long long ans=x*(x+1)/2; for(i=1;i<m;i++){ t=i;j=num=0;d=1; while(t){ if(t&1) {d*=factor[j];num++;} j++;t>>=1; } t=x/d; if(num&1) ans-=(long long)d*t*(t+1)/2;//必须加强制类型转换,否则会WA else ans+=(long long)d*t*(t+1)/2;//必须加强制类型转换,否则会WA } map<int,int>::iterator it; for(it=M.begin();it!=M.end();it++){ if(it->first>x) continue; if(gcd(it->first,p)==1) ans-=it->first; if(gcd(it->second,p)==1) ans+=it->second; } return ans; } int main(){ int i; int t,n,m; int flag,x,y,p; IsPrime(); scanf("%d",&t); while(t--){ M.clear(); scanf("%d%d",&n,&m); for(i=0;i<m;i++){ scanf("%d",&flag); if(flag==1){ scanf("%d%d%d",&x,&y,&p); int num=getPrime(p);//p素因子个数num printf("%I64d\n",find(y,num,p)-find(x-1,num,p)); }else{ scanf("%d%d",&x,&p); M[x]=p; } } } return 0; }
相关文章推荐
- HDU 4407 Sum(容斥)
- hdu 4366 Card Collector(组合数学:容斥定理)
- 解题报告: HDU_4407 Sum 容斥+暴力
- HDU 1796How many integers can you find(简单容斥定理)
- hdu 4407 Sum(容斥)
- HDU1796 How many integers can you find[容斥定理]
- hdu 1796 How many integers can you find 容斥定理
- HDU 6053 TrickGCD 【容斥定理】【莫比乌斯函数】
- HDU 5768 (中国剩余定理 容斥)
- HDU 3501 Calculation 2 【容斥定理】
- HDU 1796 How many integers can you find [容斥定理] 【组合数学】
- HDU_5794_ASimpleChess(Lucas定理&&(容斥||dp))
- HDU 1796How many integers can you find(简单容斥定理)
- hdu 4407 Sum(容斥)
- hdu 5768 - 中国剩余定理 + 容斥
- HDU 1796 How many integers can you find (容斥定理 + 二进制)
- HDU 4407 (容斥)
- HDU-2461 Rectangles 容斥定理,状态压缩
- HDU 1796How many integers can you find(简单容斥定理)
- HDU 4407 Sum(容斥)