Time Limit: 2000 MS Memory Limit: 65536 K
The Star of ACMClub 2007 @ HIT
//题意,给出n个数,求1到m中有多少个数(假设这个数是i)满足n个数中至少有一个数能够整除i;
//变形的求1~n中与m互质的数的个数问题!这里将这n个数直接当做是n个素因子,可以产生多种组合,不断筛选出能够整除1~m中得数的个数,容斥!注意的是,假如n中有两个数3和6,而m=18,对于3*6|18,计算值是1,但是12显然也能够被3、6、3*6整除,所以需要求出这k个数的最小公倍数(需要用long long,没注意错了几次)。
#include<stdio.h> #include<string.h> using namespace std; #define LL long long #define maxn 15 int a[maxn]; int gcd(int a,int b) { int c; while(b) { c=b; b=a%b; a=c; } return a; } int make_ans(int n,int m) { int ans=0,i,j,flag; LL tmp; for(i=1;i<(1<<n);i++) { tmp=1,flag=0; for(j=0;j<n&&tmp<=m;j++) if(i&(1<<j)) flag++,tmp=(LL)(a[j]/gcd(tmp,a[j]))*tmp; if(flag&1) ans+=m/tmp; else ans-=m/tmp; } return ans; } int main() { int t,n,m,i; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=0;i<n;i++) scanf("%d",&a[i]); printf("%d\n",make_ans(n,m)); } return 0; }