BZOJ1853&&P2567 [SCOI2010]幸运数字

一开始以为是数位dp

然后发现不可做,因为每一位不固定,然后就想到了dfs枚举,会TLE

令x记录当前已经枚举到了第几个数,y记录已经选了几个数,z表示这几个数的最小公倍数 

剪枝:当最小公倍数大于上界r时返回

代码

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std;
int n,m;
bool vis[100010];
lli l,r,ans,a[100010],b[100010];
inline void get(int x,lli y) 
{
    if (y>r) return;
    if (x>0) a[++m]=y;
    get(x+1,y*10+6);
    get(x+1,y*10+8);
    return ;
}
inline lli gcd(lli a,lli b)
{
    if (!b) return a;
    return gcd(b,a%b);
}
inline void dfs(int x,int y,lli z)
{
    if (x<1) 
    {
        if (y&1) ans+=(r/z-(l-1)/z);
        else if (y) ans-=(r/z-(l-1)/z);
        return ;
    }
    dfs(x-1,y,z);
    lli d=z/gcd(a[x],z);
    if ((double)a[x]*d<=r) dfs(x-1,y+1,a[x]*d);
    return ;
}
int main() 
{
    cin>>l>>r;
    get(0,0);sort(a+1,a+1+m);
    for (int i=1;i<=m;i++) 
    if (!vis[i]) 
    {
        for (int j=i+1;j<=m;j++)
            if (a[j]%a[i]==0) vis[j]=1;
        a[++n]=a[i];
    }
    dfs(n,0,1);cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/81304447