思路:从一堆数里面选四个数,而且这四个数gcd=1,问一共有多少种方案,我们考虑这四个数字gcd!=1的情况有多少种方案,然后用C(n,4)-4个数gcd!=1的情况。
计算gcd!=1的方案数,是将这N个数字每个数字都素因子分解,对于每个数num,计算出他的素因子能够组合出多少种num的因子,然后记录下来,同时还要记录这个因子是由几个素数组合成的,以便容斥时判断加减。
在计算gcd!=1的情况的时候呢,因为这N个数是不连续的,所有我有点懵,没想到咋算,看了别人题解:http://blog.csdn.net/lianai911/article/details/47609075
#include <stdio.h>
#include <string.h>
typedef __int64 LL;
int N;
int p[100];
//Count[i]表明有Count[i]个数字含有因子i
int Count[10010];
//Cnt[i]表明因子i由Cnt[i]个素数组合成
int Cnt[10010];
int plen;
void calc(int nb)
{
plen = 0;
for(int i = 2; i <= nb/i; ++i)
{
if(nb%i == 0)
{
p[plen++] = i;
while(nb%i == 0) nb /= i;
}
}
if(nb > 1) p[plen++] = nb;
for(int i = 1; i < (1<<plen); ++i)
{
int mult = 1;
int cnt = 0;
for(int j = 0; j < plen; ++j)
{
if(i&(1<<j))
{
++cnt;
mult *= p[j];
}
}
Count[mult]++;
Cnt[mult] = cnt;
}
}
//C(n,4)
LL C(int n)
{
LL nL = n;
return nL*(nL-1)*(nL-2)*(nL-3)/24;
}
int main()
{
while(scanf("%d",&N) != EOF)
{
memset(Count,0,sizeof(Count));
memset(Cnt,0,sizeof(Cnt));
int num;
for(int i = 0; i < N; ++i)
{
scanf("%d",&num);
calc(num);
}
LL res = 0;
for(int i = 2; i <= 10000; ++i)
{
if(Cnt[i]&1) res += C(Count[i]);
else res -= C(Count[i]);
}
printf("%I64d\n",C(N)-res);
}
return 0;
}