题意:http://www.lightoj.com/volume_showproblem.php?problem=1161

给你n个数  让你找出四个数 并且这四个数的最大公约数为1  问有多少种

正难则反  我们去考虑其补集  我们求出四个数的最大公约数大于1的   然后再用C(n,4)减去 剩下的就是结果

我们将每个数的因子都分解出来,就好比7个数 2,3,4,6,6,12,24

可得a[1]=7;a[2]=6;a[3]=5;a[4]=3;a[6]=4;a[8]=1;a[12]=2;a[24]=1;

从大到小 很显然在最大公约数为6的情况下有1种

同理为3有5种,为2有15种  为1的也就是全部有35种

很显然在为6的情况  重复在为3 和为2里面出现  所以我们要减去

即为3的时候有4种 为2有14种  为6有1种

所以满足的也就是16=35-4-14-1;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<math.h>
#include<string>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define N 10006
#define Lson rood<<1
#define Rson rood<<1|1
LL a[N];
LL ans[N];
void q(int x)
{
    for(int i=1;i*i<=x;i++)
    {///每个因子  只遍历一边
        if(x%i==0)
        {
            a[i]++;
            if(i*i!=x)
                a[x/i]++;
        }
    }
}
LL qq(LL x)
{
    return x*(x-1)*(x-2)*(x-3)/24;
}
int main()
{
    int T,t=1;
    scanf("%d",&T);
    while(T--)
    {
        int n,d;
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&d);
            q(d);
        }
        for(int i=10000;i>=1;i--)
        {
            ans[i]=qq(a[i]);
            for(int j=i*2;j<=10000;j+=i)
                ans[i]-=ans[j];
        }
        printf("Case %d: %lld\n",t++,ans[1]);
    }
    return 0;
}

 

posted on 2017-10-20 16:30  云胡不喜。  阅读(196)  评论(0编辑  收藏  举报