题意:给出n个数,问找出4个数满足4个数最大公约数为1,最多有多少组。
思路:容斥原理,遍历每个数的素因子,奇数个加偶数个减,然后C(n,4)-sum。
题目链接:http://poj.org/problem?id=3904
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstdlib> 5 #include <cstring> 6 #include <string> 7 using namespace std; 8 #define LL long long 9 #define N 10005 10 11 LL C[N],num[N],cnt[N],prime[N]; 12 LL n,val; 13 14 void Init(){ 15 memset(C,0,sizeof(C)); 16 for(LL i=4;i<N;i++) 17 C[i]=i*(i-1)*(i-2)*(i-3)/24; 18 } 19 20 void dfs(LL x){ 21 // memset(prime,0,sizeof(prime)); //每次都清空会浪费很多时间 22 int ct=0; 23 for(LL i=2;i*i<=x;i++){ 24 if(x%i==0){ 25 prime[ct++]=i; 26 while(x%i==0) x/=i; 27 } 28 } 29 if(x>1) prime[ct++]=x; 30 for(LL i=1;i<1<<ct;i++){ 31 LL val=1,sum=0; 32 for(LL j=0;j<ct;j++){ 33 if(i&1<<j){ 34 val*=prime[j]; 35 sum++; 36 } 37 } 38 cnt[val]++; 39 num[val]=sum; 40 } 41 } 42 43 int main(){ 44 45 // freopen("data.in","r",stdin); 46 // freopen("data.out","w",stdout); 47 48 Init(); 49 while(scanf("%lld",&n)!=EOF){ 50 memset(cnt,0,sizeof(cnt)); 51 LL sum=0; 52 for(LL i=1;i<=n;i++){ 53 scanf("%lld",&val); 54 dfs(val); 55 } 56 for(int i=2;i<N;i++) 57 if(cnt[i]){ 58 if(num[i]&1) sum+=C[cnt[i]]; 59 else sum-=C[cnt[i]]; 60 } 61 printf("%lld\n",C[n]-sum); 62 } 63 }