SPOJ-MSKYCODE Sky Code

Keywords: Programming

Inclusion-exclusion principle + dfs pruning

The number of combinations of four numbers with gcd of 1 is required. We can first find the number of combinations of four numbers without gcd of 1.

As long as all four numbers have a common prime factor, gcd is not 1

We can find all prime factors and then enumerate the product of the prime factors to find out how many can be divided by the product.

Find the number of combinations, and then use the principle of inclusion and exclusion to reduplicate them.

Because there may be many prime factors, add some pruning in dfs

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e4+10;
int a[N],num[N];
int p[N],cnt;
bool pri[N],vis[N];
void init()
{
    memset(pri,true,sizeof(pri));
    pri[1]=false;
    for(int i=2;i<N;i++)
    {
        if(pri[i])
        {
            for(int j=i+i;j<N;j+=i)
                pri[j]=false;
        }
    }
}
ll ans;
void dfs(int d,int k,int j)
{
    if(k>=N) return; //Prune
    if(k>1&&num[k]<4) return; //Prune
    if(d)
    {
        ll s=num[k];
        ll sum=s*(s-1)*(s-2)*(s-3)/2/3/4;
        if(d%2==1) ans-=sum;
        else ans+=sum;
    }
    for(int i=j;i<cnt;i++)
        if(!vis[i])
        {
            vis[i]=true;
            dfs(d+1,k*p[i],i+1);
            vis[i]=false;
        }
}
int main()
{
    init();
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        if(n<4)
        {
            printf("0\n");
            continue;
        }
        memset(num,0,sizeof(num));
        cnt=0;
        for(int i=0;i<n;i++)
        {
            int k=a[i],j;
            for(j=1;j*j<k;j++)
                if(k%j==0)
                    num[j]++,num[k/j]++;
            if(j*j==k) num[j]++;
        }
        for(int i=2;i<N;i++)
            if(pri[i]&&num[i]>=4) //At least four prime factors have occurred
                p[cnt++]=i;
        ans=1l*n*(n-1)*(n-2)*(n-3)/2/3/4;
        memset(vis,false,sizeof(vis));
        dfs(0,1,0);
        printf("%lld\n",ans);
    }
    return 0;
}

 

Posted by FSGr33n on Sat, 02 Feb 2019 00:42:16 -0800