您的位置:首页 > 其它

Codeforces 55D 数位DP

2016-02-05 19:38 344 查看
/*
找出l到r内有多少个漂亮数
漂亮数的定义是该数能被每个数位上的非零数字整除
如250是漂亮数 250%2=250%5=0

写出的bug
1.注意返回dp值得调节是flag要为false
2.下一个 状态的计算也错了。不应该写入是拆出的数位,应该是枚举的i
*/
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <set>
using namespace std;
#define ll long long
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int id[6666];
int last=0;
int get(int a,int b){
return a/gcd(a,b)*b;
}
ll dp[20][2520][66];
int q[666];
int tail=0;
ll dfs(int now,int mod,int lcm,bool flag){
if(now<0) return mod%lcm ==0;
if(!flag && dp[now][mod][id[lcm]] != -1) return dp[now][mod][id[lcm]];
int limit = flag?q[now]:9;
ll num=0;
for(int i=0;i<=limit;i++){
if(i!=0)
num += dfs(now-1, (mod*10+i)%2520, get(lcm,i), flag&&(i==limit));
else
num += dfs(now-1, mod*10%2520, lcm, flag&&(i==limit));
}
if(!flag) dp[now][mod][id[lcm]] = num;
return num;
}

ll W(ll x){
for(tail=0;x;x/=10){
q[tail++]=x%10;
}
return dfs(tail-1,0,1,true);
}
int main()
{
//freopen("in.txt","r",stdin);
memset(dp,-1,sizeof(dp));
int t;
scanf("%d",&t);
set<int > ss;
for(int st=0;st<(1<<9);st++){
int LCM=1;
for(int i=0;i<9;i++){
if(st&(1<<i)) LCM=get(LCM,i+1);
}
ss.insert(LCM);
}
for(int x : ss){
id[x] = last++;
}
while(t--){
ll l,r;
scanf("%I64d%I64d",&l,&r);
//cout<<W(r)<<endl;
//cout<<W(l-1)<<endl;
printf("%I64d\n",W(r) - W(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: