0
点赞
收藏
分享

微信扫一扫

LightOJ 1161 - Extreme GCD (容斥原理+好题)


All of you know that GCD means the greatest common divisor. So, you must have thought that this problem requires finding some sort of GCD. Don’t worry, you are absolutely right!

Given N positive integers, not necessarily distinct, how many ways you can take 4 integers from the N numbers such that their GCD is 1.

Input 
Input starts with an integer T (≤ 20), denoting the number of test cases.

Each case starts with an integer N (4 ≤ N ≤ 10000). The next line contains N integers separated by spaces. The integers will be positive and not greater than 10000.

Output 
For each case, print the case number and the number of ways you can take the integers as mentioned above.

Sample Input 


2 4 6 1 

1 2 4 6 8 
10 
12 46 100 131 5 6 7 8 9 10 
Sample Output 
Case 1: 1 
Case 2: 4 
Case 3: 195

题意:
n个数,从中选出四个数他们的gcd 是1 的方案有多少种。

思路:

直接求gcd(a,b,c,d)=1很麻烦,逆向思维,我们求选出四个数他们的gcd >1 的方案有多少种.

我们预处理处理所有数的因子个数num[i]。

  假如num[2]=5,说明n个数中有5个数中的含有因子2,ans[2]=C(5,4)代表的含义是取出4个人均含有因子2的方案数,但这并不表明取出4个人均含gcd==2的方案数,但是ans[2]-ans[2*2]-ans[3*2]-ans[4*2]........就是表明取出4个人gcd==2的方案数(因为gcd为最大公倍数,好好理解),倒着递推即可,最后的答案为ans[1]。

#include <stdio.h>  
#include <string.h>
#include <iostream>
#define N 10005
using namespace std;
const int MOD=10056;
typedef long long ll;
ll num[N],ans[N];
void f(ll t) //num保存这x的因子
{

for(ll i=1;i*i<=t;i++)
{
if(t%i==0)
{
num[i]++;
if(i*i!=t)
num[t/i]++;
}
}
}
ll cal(ll x)
{
return x*(x-1)*(x-2)*(x-3)/24;
}
int main()
{

int T;
scanf("%d",&T);
int k=1;

while(T--)
{
memset(num,0,sizeof(num));
int n;
scanf("%d",&n);
ll v;
for(int i=0;i<n;i++)
{
scanf("%lld",&v);
f(v);
}
for(int i=N;i>=1;i--)
{
ans[i]=cal(num[i]);
for(int j=i*2;j<=N;j+=i)
ans[i]-=ans[j];
}
printf("Case %d: %lld\n",k++,ans[1]);
}
return 0;
}

 

举报

相关推荐

0 条评论