●BZOJ 2393 Cirno的完美算数教室

题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=2393

题解:

容斥原理,暴力搜索,剪枝
...和
[Scoi2010 幸运数字] 一样的(只是那个题是 6,8,这个题是2,9)

代码:

#include<cstdio> 
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
bool mark[3000];
ll luck[3000],l,r,ans;
int cnt; bool fg;
ll gcd(ll a,ll b){
    while(b^=a^=b^=a%=b);
    return a;
}
void dfs(int p,int num,ll val,const ll &lim){
    if(!p) return;
    ll LCM=val/gcd(val,luck[p])*luck[p];
    if(0<LCM&&LCM<=lim) ans+=1ll*lim/LCM*((num+1)%2?1:-1),dfs(p-1,num+1,LCM,lim);
    dfs(p-1,num,val,lim);
}
ll solve(ll lim){
    ans=0;
    dfs(cnt,0,1,lim);
    return ans;
}
void pre(int dep,ll val){
    if(val) luck[++cnt]=val;
    if(!dep) return;
    pre(dep-1,val*10+2);
    pre(dep-1,val*10+9);
}
int main()
{
    pre(10,0); int ccnt=0;
    sort(luck+1,luck+cnt+1);
    for(int i=1;i<=cnt;i++)
        for(int j=1;j<i;j++) if(luck[i]%luck[j]==0) mark[i]=1;
    for(int i=1;i<=cnt;i++) if(!mark[i]) luck[++ccnt]=luck[i]; cnt=ccnt;
    scanf("%lld%lld",&l,&r); 
    printf("%lld",solve(r)-solve(l-1));
    return 0;
}


posted @ 2017-12-12 19:28  *ZJ  阅读(155)  评论(0编辑  收藏  举报