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
分析:让你选出4元组,GCD(a,b,c,d)=1,问方案数开始并没有什么思路
我们想不考虑条件的总的方案数为:C(n,4),这其中我们要去掉GCD>1的
那么我们就要考虑素数因子之间的组合来容斥
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
int n,A[10100];
int num[10100];
int kind[10100];
LL f[10010],ans;
int v[10];
void init()
{
for(int i=4;i<=10000;i++)
f[i]=1LL*i*(i-1)*(i-2)*(i-3)/24;
}
void solve(int x)
{
int m=0;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
while(x%i==0)
x/=i;
v[m++]=i;
}
}
if(x>1)
v[m++]=x;
for(int i=1;i<(1<<m);i++)
{
int c=0,l=1;
for(int j=0;j<m;j++)
{
if(i&(1<<j))
{
c++;
l*=v[j];
}
}
num[l]++;
kind[l]=c;
if(c&1)
{
ans-=f[num[l]-1];
ans+=f[num[l]];
}
else
{
ans+=f[num[l]-1];
ans-=f[num[l]];
}
}
}
int main()
{
init();
while(~scanf("%d",&n))
{
CLEAR(num,0);
CLEAR(kind,0);
ans=0;
REPF(i,1,n)
{
scanf("%d",&A[i]);
solve(A[i]);
}
printf("%lld\n",f[n]-ans);
}
return 0;
}