Cogs 513. 八(容斥原理)


  1. ★☆ 輸入文件:eight.in 輸出文件:eight.out 簡單對比
    時間限制:1 s 內存限制:128 MB
    【問題描述】
    八是個頗有趣的數字啊。八=發,八八=爸爸,88=拜拜。固然最有趣的仍是8用二進制表示是1000。怎麼樣,有趣吧。固然題目和這些都沒有關係。
    某我的很無聊,他想找出[a,b]中能被8整除卻不能被其餘一些數整除的數。
    【輸入文件】
    第一行一個數n,表明不能被整除的數的個數。第二行n個數,中間用空格隔開。第三行兩個數a,b,中間一個空格。
    【輸出文件】
    一個整數,爲[a,b]間能被8整除卻不能被那n個數整除的數的個數。
    【樣例輸入】
    eight.in
    3
    7764 6082 462
    2166 53442
    【樣例輸出】
    eight.out
    6378
    【數據規模】
    對於30%的數據, 1≤n≤5,1≤a≤b≤100000。
    對於100%的數據,1≤n≤15,1≤a≤b≤10^9,N個數全都小於等於10^4大於等於1。
/* 一道容斥一眼題. 全集就是[l,r]中8的倍數的個數了. 考慮不合法的部分就是8的其餘數的LCM了 n這麼小 二進制拆分一下枚舉子集就行了. */
#include<iostream>
#include<cstdio>
#define MAXN 20
#define LL long long
using namespace std;
LL n,a[MAXN],l,r,ans,tot,Lcm;
LL gcd(LL a,LL b)
{
    if(!b) return a;
    return gcd(b,a%b);
}
LL lcm(LL a,LL b)
{
    return a*b/gcd(a,b);
}
void slove()
{
    ans=r/8-(l-1)/8;
    for(int s=1;s<=(1<<n)-1;s++)
    {
        tot=0;Lcm=8;
        for(int i=0;i<n;i++)
          if(s&(1<<i)) tot++,Lcm=lcm(Lcm,a[i]);
        if(tot&1) ans-=r/Lcm-(l-1)/Lcm;
        else ans+=r/Lcm-(l-1)/Lcm;
    }
}
int main()
{
    freopen("eight.in","r",stdin);
    freopen("eight.out","w",stdout);
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    scanf("%d %d",&l,&r);
    slove();
    printf("%d",ans);
    return 0;
}
相關文章
相關標籤/搜索