POJ_3904_Sky Code

来源:互联网 发布:xampp linux 启动 编辑:程序博客网 时间:2024/05/16 11:35
Sky Code
Time Limit: 1000MS
Memory Limit: 65536KTotal Submissions: 2611
Accepted: 852

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

42 3 4 5 42 4 6 8 72 3 4 5 7 6 8

Sample Output

1 0 34

Source

Southeastern European Regional Programming Contest 2008

  • 题目是要在n个数中找到一个四元组使得(A,B,C,D)==1
  • 问有多少种组合
  • 恩,暴力会出事的,没有奇迹
  • 那既然题目里偏向gcd,那就考虑考虑同余和整除
  • 同余方程就算了,试试能不能用莫比乌斯反演来进行解答
  • 我们令 f(x)=n.count(x==gcd(A,B,C,D)); 即gcd四元组为x的全部组数
  • 关于莫比乌斯反演可以看dalao的讲解
  • 其中莫比乌斯反演的两种形式至关重要


  • 我们这里应用第二种
  • 那么有:
  • f(1)=sigma(u[d]*F[d]);
  • 这里有个问题啊,就是F(x)怎么求
  • 它要求的是sigma所有gcd为x的倍数的f(d);
  • 我刚开始不懂啊,很僵硬啊~
  • 然后过了很长时间我才想到这样一个式子算是解决这个问题
  • gcd(a,b)==1;gcd(a*k,b*k)==k;
  • 所以说如果我们把具有同一因数的数的所有组合找到,那就是找到了所有gcd的可能值
  • 这里我们不需要知道各个四元组的具体数值,我们只用知道总值即可
  • 用组合公式C(n,4)计算F(n);当然前提是n>4;
  • 莫比乌斯反演系数打表就不说了,代码里有
  • 这题主要是想莫比乌斯反演的函数比较头疼
  • 还有就是对于F(x)的求解

#include <iostream>#include <string>#include <cstdio>#include <cstring>#include <algorithm>#include <climits>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>using namespace std;typedef long long           LL ;typedef unsigned long long ULL ;const int    maxn = 10000 + 10 ;const int    inf  = 0x3f3f3f3f ;const int    npos = -1         ;const int    mod  = 1e9 + 7    ;const int    mxx  = 100 + 5    ;const double eps  = 1e-6       ;int c[maxn], mu[maxn];LL F(LL n){return ((n)*(n-1)*(n-2)*(n-3))/24;}void getMu(void){// for(int i=1;i<maxn;i++)// mu[i]=1;for(int i=1;i<maxn;i++){int target=i==1?1:0;int delta=target-mu[i];mu[i]=delta;for(int j=i+i;j<maxn;j+=i)mu[j]+=delta;}}void factors(int n){int t=sqrt(n);for(int i=1;i<=t;i++)if(0==n%i){c[i]++;c[n/i]++;}if(t*t==n)c[t]--;}int n, a;LL ans;int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout);getMu();while(~scanf("%d",&n)){memset(c,0,sizeof(c));for(int i=0;i<n;i++){scanf("%d",&a);factors(a);}ans=0;for(int i=1;i<maxn;i++)if(mu[i] || c[i]>4)ans+=mu[i]*F(c[i]);printf("%lld\n",ans);}return 0;}


原创粉丝点击