POJ 3904 Sky Code (容斥原理)

来源:互联网 发布:买别人的淘宝店铺 编辑:程序博客网 时间:2024/05/19 16:21

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


POJ 3904 Sky Code

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<vector>#include<algorithm>#define mem(a,x) memset(a,x,sizeof(a))using namespace std;typedef long long ll;const int inf = 0x3f3f3f3f;/*ans = 总的排列组合数 - 四个数公因数不为1的组合四个数公因数不为一必须两两不互质四个数公因数不为1的组合数 = 由一个素因子组合成的4个数- 由两个素因子组合成的四个数  + 由三个......容斥原理 -- 奇加偶减 */ const int N = 100004;ll p[N];//p[i]保存分解的素因子 ll c[N];//c[i]表示从i个数选4个数的排列ll t[N];//t[i]表示数字i可以分解成几个素数ll cnt[N];//cnt[i]表示输入的所有数中包含因子i的个数 void init(){for (ll i = 4;i < N;++i){c[i] = i*(i-1)*(i-2)*(i-3)/24LL;}}void fool(ll n){ll x = n;int tot = 0;for (int i = 2;i*i <= x;++i){if (x%i == 0){p[tot++] = i;while (x%i == 0){//多个为i的素因子全部除掉减少循环x /= i;}}}if (x > 1) p[tot++] = x;for (int i = 1;i < (1<<tot);++i){//最后一个//素因子的排列组合 比如素因子是{2,3,7,13}那么1100 就是2和3的组合6 ll s = 1;//当前状态的所有素因子组合而成的数ll st = 0;//当前状态中1的个数,也即是素因子的个数for (int j = 0;j < tot;++j){if (i&(1<<j)){//这一位是1 s*=p[j];st++;}} cnt[s]++;//当前这个数n有s这样的素因子 t[s] = st;//这个因子中素因子的个数 }}int main(){init();ll n;while(cin>>n){mem(cnt,0);ll mx = -inf;for (int i = 1;i <= n;++i){ll x;scanf("%lld",&x);mx = max(mx,x);fool(x);}ll ans = 0;for (int i = 0;i < mx;++i){if (cnt[i]){if (t[i]&1){//奇数个素因子组合而成 ans += c[cnt[i]];}else ans -= c[cnt[i]]; }}//cout<<ans<<endl;printf("%lld\n",c[n]-ans);} return 0;}


0 0
原创粉丝点击