BZOJ1853: [Scoi2010]幸运数字
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1853
并不是数位dp。
容斥原理。做出所有的幸运数字,然后再跑一下它的倍数,由于会有重复。所以容斥一下。。
注意两个10^10相乘会爆long long
#include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstdio> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 20050 #define ll long long using namespace std; ll l,r,ans,a[maxn],b[maxn]; int n,m,vis[maxn]; ll read(){ ll x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); } while (isdigit(ch)){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } void pre(ll x){ if (x>r) return; if (x!=0&&x<=r) a[++m]=x; pre(x*10+6); pre(x*10+8); } ll gcd(ll x,ll y){ if (y==0) return x; return gcd(y,x%y); } void dfs(int x,int y,ll 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); ll tmp=z/gcd(z,a[x]); if (((double)a[x]*tmp)<=r) dfs(x+1,y+1,a[x]*tmp); } int main(){ l=read(); r=read(); pre(0); sort(a+1,a+m+1); rep(i,1,m) if (!vis[i]){ b[++n]=a[i]; rep(j,i+1,m){ if (a[j]%a[i]==0&&vis[j]==0) vis[j]=1; } } rep(i,1,n) a[n-i+1]=b[i]; dfs(1,0,1); printf("%lld\n",ans); return 0; }