标签: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