Discussion
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
題意
在給定個數中選4個數,是他們的最大公約數爲1,求有幾種選擇方式。
思路
利用容斥原理,從M個數中選4個一共有
C(m,4) 中,減去最大公約數不唯一的即可。
將一個數進行因式分解,會得到它的因子,如果將所以數都進行因式分解,如果其中的某4個數具有相同的因子,那麼說明這四個數不能給選到一起,用C(m,4) 減掉這些情況就好,那麼問題來了,比如,現在這些數,以2爲因子的數有x個,以3爲因子的有y個,那麼要用C(m,4)−C(x,4)−C(y,4) 但是又有些數既以2爲因子又以3爲因子,這說明多減了,還要加上以2,3爲因子的數,這就是容斥原理。
代碼
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 10005;
int a[maxn];
int prime[maxn];
bool vis[maxn];
long long cx4(int x)
{//求c(x,4)
return (long long )x*(x-1)*(x-2)*(x-3)/24;
}
void gao(int n)
{//搞一下
int top = 0;
for(int i = 2; i*i <= n; i++)
{
if(n % i == 0)
prime[top++] = i;
while(n % i == 0)
n /= i;
}
if(n > 1)
prime[top++] = n;
for(int i = 1; i < (1 << top); i ++)
{
int temp = 1;
bool flag = false;
for(int j = 0; j < top; j ++)
if( i & 1 << j)
{//這裏是神奇代碼,實現容斥。
temp *= prime[j];
flag = ! flag;
}
a[temp] ++;
vis[temp] = flag;
}
}
int main()
{
int t;
while( cin >> t)
{
memset(a,0,sizeof(a));
memset(prime,0,sizeof(prime));
for(int i = 0; i < t; i ++)
{
int m;
cin >> m;
gao(m);
}
long long ans = cx4(t);
for(int i = 0; i <= maxn; i ++)
{
if(a[i])
{
if(vis[i])
ans -= cx4(a[i]);
else
ans += cx4(a[i]);
}
}
cout << ans << endl;
}
return 0;
}