Sky Code
Time Limit: 1000MS | Memory Limit: 65536K | |
Total 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
4
2 3 4 5
4
2 4 6 8
7
2 3 4 5 7 6 8
Sample Output
1
0
34
Source
- 题目是要在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;
}