POJ 3904 Sky Code

来源:互联网 发布:网络销售有哪些类型 编辑:程序博客网 时间:2024/05/19 16:23

题目链接:http://poj.org/problem?id=3904


题意:在n个数中找出四元组的数量(四元组中的四个数的最大公约数为1)。


思路:可以用全部四元组的数量减去最大公约数不是1的四元组的数量。
我们将n个数一个个分解质因数,如果ai是质数x的倍数,那么就fact[x]++,那么最后C(fact[i],4)就是以i为倍数形成四元组的数量。
但是比如:6,12,18,24 这组既会被i=2的时候统计一次,又会被i=3的时候统计一次,所以用容斥去计算答案。


#include <cstdio>#include <cmath>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#include <stack>#include <map>#include <queue>#include <utility>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))#define LL long long#define ULL unsigned long long#define inf 0x7fffffff#define mod %100000007int n;int time[10009];int num[10009];int fact[20];LL f(int n)  {    LL ans = 1;    ans*=n;    ans*=n-1;    ans*=n-2;    return ans*(n-3)/24;}void init(int x){    int m = 0;    int temp = x;    for(int i = 2; i*i <= temp; i++)    {        if ( temp % i == 0 )        {            fact[m++] = i;            while( temp % i == 0 ) temp /= i;        }    }    if ( temp > 1 ) fact[m++] = temp;    int uplim = 1<<m;    rep(i,1,uplim-1)    {        int cnt = 1;        int t = 0;        rep(j,0,m-1)            if ( i & (1<<j) )            {                t++;                cnt*=fact[j];            }        time[cnt]++;        num[cnt] = t;    }}int main(){    while(~scanf("%d",&n))    {        Clean(num,0);        Clean(time,0);        int x;        rep(i,1,n)        {            scanf("%d",&x);            init(x);        }        LL ans = f(n);        rep(i,2,10000)            if ( time[i]>3 )            {                if ( num[i] & 1 ) ans-=f(time[i]);                else ans+=f(time[i]);            }        cout<<ans<<endl;    }    return 0;}


0 0
原创粉丝点击