//求质数 #include<stdio.h> int main() { __int64 a[100],num,i,n; while(scanf("%I64d",&n)!=EOF) { num=0; for(i=2;i*i<=n;i++) { if(n%i==0) { a[num++]=i; while(n%i==0) n=n/i;//除几次就说明乘几次,一个数由质数乘得 } } if(n>1) a[num++]=n; for(i=0;i<num;i++) printf("%I64d ",a[i]); printf(" "); } return 0; }
hdu 4135(容斥原理)
题意:就是让你求(a,b)区间于n互质的数的个数.
Input
The first line on input contains T (0 < T <= 100) the number of test cases, each of the next T lines contains three
integers A, B, N where (1 <= A <= B <= 1015) and (1 <=N <= 109).
Output
For each test case, print the number of integers between A and B inclusive which are relatively prime to N. Follow
the output format below.
Sample Input
2
1 10 2
3
15 5
Sample Output
Case #1: 5
Case #2: 10
第一步:求出n的质因子:2,3,5;
第二步:(1,m)中是n的因子的倍数当然就不互质了(2,4,6,8,10)->n/2 6个,(3,6,9,12)->n/3 4个,(5,10)->n/5 2个。
如果是粗心的同学就把它们全部加起来就是:6+4+2=12个了,那你就大错特错了,里面明显出现了重复的,我们现在要处
理的就是如何去掉那些重复的了!
第三步:这里就需要用到容斥原理了,公式就是:n/2+n/3+n/5-n/(2*3)-n/(2*5)-n/(3*5)+n/(2*3*5).
第四步:我们该如何实现呢?我在网上看到有几种实现方法:dfs(深搜),队列数组,位运算三种方法都可以!上述公式有
一个特点:n除以奇数个数相乘的时候是加,n除以偶数个数相乘的时候是减。我这里就写下用队列数组如何实现吧:我
们可以把第一个元素设为-1然后具体看代码如何实现吧!
同种类型的题目:hdu 2841 hdu1695
#include <stdio.h> #include <stdlib.h> long long a[1000],num;//a存质数 void init(long long n)//求一个数的质因子(规定记住) { long long i; num=0; for(i=2;i*i<=n;i++) { if(n%i==0) { a[num++]=i; while(n%i==0) n=n/i; } } if(n>1) a[num++]=n; } long long haha(long long m)//用队列数组实现容斥原理模板 { long long que[10000],i,j,k,t=0,sum=0; que[t++]=-1; //循环相乘,容斥,减去多算的,再相加,用-1加减,k=t,判断与谁乘 for(i=0;i<num;i++) { k=t; for(j=0;j<k;j++) que[t++]=que[j]*a[i]*(-1); } for(i=1;i<t;i++) sum=sum+m/que[i]; return sum; } int main() { long long T,x,y,n,sum; long long i; while(scanf("%lld",&T)!=EOF) { for(i=1;i<=T;i++) { scanf("%lld%lld%lld",&x,&y,&n); init(n); sum=y-haha(y)-(x-1-haha(x-1));//所有点的个数y减去1~y不与n互质的个数, printf("Case #%lld: ",i); //再加上1~x里不与n互质的个数,再减去1~x所有点个数 printf("%lld ",sum); } } return 0; }
借鉴 :ACM不懈追求~http://www.cnblogs.com/jiangjing/archive/2013/06/03/3115470.html