您的位置:首页 > 其它

bzoj2393/bzoj1853 Cirno的完美算数教室/[Scoi2010]幸运数字 搜索+容斥

2017-12-23 18:32 316 查看
这两个题是完全一样的,但1853会爆long long,中间要用long double估计一下。

popo大神的题解:http://blog.csdn.net/popoqqq/article/details/41807333

题目大意:求在[L,R]中能被“baka数”整除的数的个数.baka数是数位组成只含2和9(⑨)的数.范围1e10-1e11.

先预处理出所有baka数,再把是另一个的倍数的删去,这里暴力即可.

如果个数少的话显然是一个求lcm的容斥,但复杂度是2^n的

所以这里用搜索+剪枝

还是枚举每个数选与不选,当当前的lcm大于R就剪枝

倒着从大到小枚举也可以加快速度

//BZOJ2393
#include <bits/stdc++.h>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=2005;
int vist
,c1,tot;
LL l,r,a
,ans;
LL gcd(LL a,LL b)
{
if(!b)return a;
return gcd(b,a%b);
}
void dfs1(LL x)
{
if(x>r)return;
a[++c1]=x;
dfs1(x*10+2);dfs1(x*10+9);
}
void dfs2(int now,int f,LL x)
{
if(now==0){
if(x>1)
ans+=(r/x-(l-1)/x)*f;
return;
}
dfs2(now-1,f,x);
LL lcm=a[now]*x/gcd(a[now],x);
if(lcm>r)return;//
dfs2(now-1,-f,lcm);
}
int main()
{
scanf("%lld%lld",&l,&r);
dfs1(2);dfs1(9);
sort(a+1,a+c1+1);
for(int i=1;i<c1;i++)
for(int j=i+1;j<=c1;j++)
if(a[j]%a[i]==0)vist[j]=1;
for(int i=1;i<=c1;i++)
if(!vist[i])a[++tot]=a[i];
dfs2(tot,-1,1);
printf("%lld\n",ans);
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: