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

这两个题是完全一样的,但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[N],c1,tot;
LL l,r,a[N],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;
}




猜你喜欢

转载自blog.csdn.net/wolf_reiser/article/details/78881469