gdut 2016校赛决赛 Problem F 我是好人4

广工校赛时遇到这道题10E大的数打表肯定不行,起初我想到了直接相除,然后减去他们的最小公倍数,当然只限于有两个数,三个数的话就有点懵了,不知道怎么加减,四个数更别提了,而题目是50个数,当时还不知道容斥原理,怎么想也想不明白到底应该怎么写,比赛时这道题的AC的人也特别的少。赛完百度了下才知道容斥原理这个词,即:

A1并A2并A3并.....An =   A1+A2+..An-        (  A1交A2  +  A1A3  +  A1交A4  +....  An-1交An  )    +    (A1交A2交A3  +  A1交A2交A4 + ....An-2交An-1交An)  -     (-1)^n*(A1交A2交A3交...An); 

利用这个原理将所有情况加减一遍就算出来了

Problem F: 我是好人4

Description

众所周知,我是好人!所以不会出太难的题,题意很简单

给你n个数,问你1000000000(含1e9)以内有多少个正整数不是这n个数任意一个的倍数

最后友情提供解题代码(我真是太好人了)

void solve(int p[], int n)

{

int ans = 0;

for (int i = 1; i <= 1e9; i++)

{

int fl = 0;

for (int j = 0; j < n; j++)

{

if (i % p[j] == 0)

{

fl = 1;

break;

}

}

if (fl == 0)ans++;

}

printf("%d\n", ans);

}

Input

第1行是一个整数T,表示共T组数据。 接下来是T组数据,每组数据第1行是正整数n(n<=50),接下来是n个正整数(小于等于1000),任意两数用1个空格隔开,最前数前面与最后数后面无空格

Output

输出T行,对应T组数据。(T<=10) 每行输出这样的正整数有多少个

Sample Input

342 3 5 71213854 101 143 282 538 922 946 286 681 977 892 656 907

Sample Output

228571428500000000968701719

代码:
#include<stdio.h>
#include<string.h>
#define ll long long
#define maxn 1000000000
ll a[60],b[60],k,s=0;
ll gcd(ll c, ll d)
{
    return d?gcd(d,c%d):c;
}
ll lcm(ll c,ll d)
{
    return c*d/gcd(c,d);
}
void dfs(ll qi,ll shu,ll mo)
{
    if(qi==k)
    {
        if(mo)
        {
            if(mo&1)
                s-=maxn/shu;
            else
                s+=maxn/shu;
        }
        return;
    }
    if(shu%a[qi]==0) return;
    dfs(qi+1,shu,mo);
    shu=lcm(a[qi],shu);
    if(shu<=maxn)
        dfs(qi+1,shu,mo+1);
}
int main()
{
    ll N;
    scanf("%lld",&N);
    while(N--)
    {
        k=0;
        ll j,n,i;
        scanf("%lld",&n);
        for(i=0; i<n; i++)
            scanf("%lld",&b[i]);
        for(i=0; i<n; i++)
        {
            for(j=0; j<n; j++)
            {
                if(j==i||b[j]==-1)
                    continue;
                if(b[i]==-1)
                    break;
                if(b[i]%b[j]==0)
                {
                    b[i]=-1;
                    break;
                }
            }
        }
        memset(a,0,sizeof(a));
                int f=0;
        for(i=0; i<n; i++)
        {
            if(b[i]!=-1)
                a[k++]=b[i];
                if(b[i]==1)
                 f=1;
        }
        s=maxn;
        if(f)
        {
            printf("0\n");
            continue;
        }
        dfs(0 ,1 ,0 );
        printf("%lld\n",s);
    }
}
 

你可能感兴趣的:(容斥原理)