Sky Code(POJ-3904)

Problem Description

Stancu likes space travels but he is a poor software developer and will never be able to buy his own spacecraft. That is why he is preparing to steal the spacecraft of Petru. There is only one problem – Petru has locked the spacecraft with a sophisticated cryptosystem based on the ID numbers of the stars from the Milky Way Galaxy. For breaking the system Stancu has to check each subset of four stars such that the only common divisor of their numbers is 1. Nasty, isn’t it? Fortunately, Stancu has succeeded to limit the number of the interesting stars to N but, any way, the possible subsets of four stars can be too many. Help him to find their number and to decide if there is a chance to break the system.

Input 

In the input file several test cases are given. For each test case on the first line the number N of interesting stars is given (1 ≤ N ≤ 10000). The second line of the test case contains the list of ID numbers of the interesting stars, separated by spaces. Each ID is a positive integer which is no greater than 10000. The input data terminate with the end of file.

Output

For each test case the program should print one line with the number of subsets with the asked property.

Sample Input

4
2 3 4 5 
4
2 4 6 8 
7
2 3 4 5 7 6 8

Sample Output



34

题意:多组数据,每组数据给出 n 个数构成一个集合,问有多少个不同的含有四个元素的子集 (a,b,c,d) 他们的最大公约数为 1

思路:

题目本质是要求有多少个 (a,b,c,d) 的 GCD(a,b,c,d)=1 

设 F(k) 为有多少对(a,b,c,d)满足 GCD(a,b,c,d)=k 的个数的倍数,f(k) 为有多少对(x,y)满足 GCD(a,b,c,d)=k 的个数

因此,有:F(k)=\sum_{k|d}f(d),可以看出,其符合莫比乌斯反演的形式

那么有:F(k)=\sum_{k|d}f(d) \Leftrightarrow f(n)=\sum_{k|d} u(\frac{d}{k})F(d)

根据 F(k) 的定义可知,只要在原来的集合中找出能被 n 整除的数的个数 m,然后 C(m,4) 即为 F(n)

由于要求 GCD(a,b,c,d)=1,因此对于 f(k),k 取 1 即为答案

因此,可得:f(1)=u(1)F(1)+u(2)F(2)+...+u(maxx)F(maxx),maxx=N,其中 N 是数据范围

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 10000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;

LL n;
LL mu[N],prime[N];
bool bprime[N];
LL a[N],num[N];
void getMu(LL n){//线性筛求莫比乌斯函数

    mu[1]=1;//根据定义,μ(1)=1

    LL cnt=0;
    memset(bprime,false,sizeof(bprime));
    for(LL i=2;i<=n;i++){//求2~n的莫比乌斯函数
        if(!bprime[i]){
            prime[cnt++]=i;//存储质数
            mu[i]=-1;//i为质数时,μ(1)=-1
        }
        for(LL j=0;j<cnt;j++){//枚举i之前的素数个数
            LL k=i*prime[j];//素数的乘积
            if(k>n)//剪枝
                break;
            bprime[k]=true;//不是质数
            if(i%prime[j])//i不是primes[j]的整数倍时,i*prime[j]就不会包含相同质因子
                mu[k]=-mu[i];//mu[k]=mu[i]*mu[prime[j]],因为prime[j]是质数,mu值为-1
            else{
                mu[k]=0;
                break;//留到后面再筛
            }
        }
    }
}
LL Cn4(LL m){
    if(m==0)
        return 0;
    return m*(m-1)*(m-2)*(m-3)/24;
}
void getM(){
    memset(num,0,sizeof(num));
    for(LL i=0;i<n;i++){
        LL x=a[i];
        LL m=sqrt(x);
        for(LL j=1;j<=m;j++){
            if(x%j==0){
                num[j]++;
                num[x/j]++;
            }
        }
        if(m*m==x)
            num[m]--;
    }
}
int main(){
    getMu(N);
    while(scanf("%lld",&n)!=EOF&&n){
        for(LL i=0;i<n;i++)
            scanf("%lld",&a[i]);
        getM();

        LL res=0;
        for(LL i=1;i<N;i++)
            res+=mu[i]*Cn4(num[i]);
        printf("%lld\n",res);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值