bzoj1853: [Scoi2010]幸运数字 dp+容斥原理

来源:互联网 发布:广州知用中学礼仪服 编辑:程序博客网 时间:2024/05/21 12:42

很明显,把只有6和8组成的数都找出来。

然后我们考虑只有6和8的情况 那么就是lim/6+lim/8-lim/LCM(6,8)

很明显是个容斥原理,然后我们可以发现范围内的只有6和8的数中互质的数只有10几个所以容斥的复杂度是可以接受的

此题求LCM会爆longlong然后就会TE 不要问我为什么,亲测。

用double求近似值作比较,然后枚举顺序要从大到小

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>using namespace std;#define maxn 11000typedef long long sint;sint l,r;int t,n,m;sint ans;sint a[maxn],b[maxn];bool vis[maxn];sint gcd(sint a,sint b){    if(b==0) return a;    return gcd(b,a%b);}sint lcm(sint x,sint y){    return x/gcd(x,y)*y;}void pre(int x,sint y){    if(y>r)return;    if(x>0)a[++m]=y;    pre(x+1,y*10+6);    pre(x+1,y*10+8);}void dfs(int x,int y,sint z){    if(x>n)    {        if(y&1)ans+=r/z-(l-1)/z;        else if(y)ans-=r/z-(l-1)/z;        return;    }    dfs(x+1,y,z);    sint tmp=z/gcd(a[x],z);    if(((double)a[x]*tmp)<=r)       dfs(x+1,y+1,a[x]*tmp);}int main(){    scanf("%lld%lld",&l,&r);    pre(0,0);    sort(a+1,a+m+1);    for(int i=1;i<=m;i++)    if(!vis[i])    {        b[++n]=a[i];        for(int j=i+1;j<=m;j++)            if(!(a[j]%a[i]))                vis[j]=1;    }    for(int i=1;i<=n;i++)       a[n-i+1]=b[i];    dfs(1,0,1);    printf("%lld",ans);    return 0;}

0 0