一开始看 这里 这个文章博主写得很好。
当举容斥定理的所谓 奇数为负 偶数为正的时候。
我直接就认为是 a*b 了。实际上是lcm(a,b)。
由于博文中的因子都是互素的(素数之间)。所以lcm(a,b) = a*b。
用队列数组做的。比较简单干净点。原理就不解释了吧。容斥定理。可以看相关论文。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> __int64 queue[100000]; int M[25]; int num2,num1; int t; __int64 gcd(__int64 a,__int64 b) { if(a>b){t=a;a=b;b=t;} if(a==0){return b;} return gcd(b%a,a); } __int64 lcm(__int64 a,__int64 b) { return a/gcd(a,b)*b; } void Init(int tot) { int i,j; num1 = num2=1; queue[0] = -1; for(i=0;i<tot;i++) { if(M[i]==0){continue;} for(j=0;j<num1;j++) { if(queue[j]<0) { queue[num2++] = lcm(-queue[j],M[i]); } else { queue[num2++] = -lcm(queue[j],M[i]); } } num1 = num2; } } int main() { __int64 n; int m; int i,j; __int64 count; while(scanf("%I64d%d",&n,&m)!=EOF) { count = 0; int tot = 0; for(i=0;i<m;i++) { scanf("%d",&M[tot++]); } Init(tot); for(i=1;i<num2;i++) { count += (n-1)/queue[i]; } printf("%I64d ",count); } } /* Output Limit Exceeded 多写了几个输出。 Time Limit. 数组开太小。 WR 没有重复的样例输入 */