[BZOJ 1853][Scoi2010]幸运数字:容斥原理

点击这里查看原题

因为最多有10位,所以最多有2+4+…+1024=2046个数,去掉存在倍数关系的数,对剩余的数做容斥

/*
User:Small
Language:C++
Problem No.:1853
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
int head,cnt,n;
bool vis[2100];
ll a[2100],b[2100];
ll ans,l,r;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
void dfs(int now,ll sum,int cnt){
    if(now==n+1){
        if(cnt==0) return;
        if(cnt&1) ans+=r/sum-(l-1)/sum;
        else ans-=r/sum-(l-1)/sum;
        return;
    }
    dfs(now+1,sum,cnt);
    ll tmp=sum/gcd(sum,b[now]);
    if((double)tmp*b[now]<=r){
        dfs(now+1,tmp*b[now],cnt+1);
    }
}
int main(){
    freopen("data.in","r",stdin);//
    while(cnt<2046){
        a[++cnt]=a[head]*10+6;
        a[++cnt]=a[head]*10+8;
        head++;
    }
    for(int i=1;i<=cnt;i++)
        if(!vis[i]){
            b[++n]=a[i];
            for(int j=i+1;j<=cnt;j++)
                if(a[j]%a[i]==0) vis[j]=1;
        }
    for(int i=1;i<=n/2;i++) swap(b[i],b[n+1-i]);
    scanf("%lld%lld",&l,&r);
    dfs(1,1,0);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/SmallSXJ/article/details/72823822