标签:poj
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1694 | Accepted: 523 |
Description
Input
Output
Sample Input
4 2 3 4 5 4 2 4 6 8 7 2 3 4 5 7 6 8
Sample Output
1 0 34
题意:给定n个数a1,a2,a3,…,an,从中选出四个数,使得他们之间的最大公约数为1,问有多少种取法?
解题思路:对每一个数ai,我们对它进行质因数分解,然后利用2^k算法找出所有由质因数组成的数,并记录组成该数的质因数个数,最后运用容斥原理进行求解;
参考代码:
#include <iostream> #include <string.h> using namespace std; #define MAX_N 10000+5 #define MAX_FACTOR 16 typedef long long ll; int n,f[MAX_N],count[MAX_N],factor[MAX_FACTOR],factor_num[MAX_N]; void solve(int a){ int k=0; for (int i=2;i*i<=a;i++){ //质因数分解 if (a%i==0){ factor[k++]=i; while (a%i==0) a/=i; } } if (a>1) factor[k++]=a; for (int i=1;i<(1<<k);i++){ //2^k算法 int mul=1,bits=0; for (int j=0;j<k;j++){ if (i&(1<<j)){ bits++; mul*=factor[j]; } } count[mul]++; factor_num[mul]=bits; } } ll cal(ll a){ return a*(a-1)*(a-2)*(a-3)/24; } int main(){ while (cin>>n){ for (int i=0;i<n;i++) cin>>f[i]; memset(count,0,sizeof(count)); memset(factor_num,0,sizeof(factor_num)); for (int i=0;i<n;i++) solve(f[i]); ll ans=cal(n); for (int i=2;i<=10000;i++){ if (factor_num[i]&1==0){ ans+=cal(count[i]); } else{ ans-=cal(count[i]); } } cout<<ans<<endl; } return 0; }
标签:poj
原文地址:http://blog.csdn.net/codeforcer/article/details/43971051