【数位DP】 【CodeForces 55D】

来源:互联网 发布:修改服务器端口 编辑:程序博客网 时间:2024/04/30 00:45

原题直通车:CodeForces 55D Beautiful numbers

题意:求区间[a, b]中有多少个数能整除自身的每个非0数位。

分析:一个数位只有1~9种可能,而1~9的lcm=2520。满足要求的数所有数位的lcm一定是2520的因子,

      所以可先求出2520的所有因子,一开始都对2520取mod,这样对结果没有任何影响,最后再对所有数

      位的lcm取mod,如果为0则满足。

代码:


#include<iostream>#include<cstdio>#include<cstring>#include<map>using namespace std;typedef long long LL;const int maxn=2520;int digit[20], a[50], t=0;LL dp[20][maxn][50];map<int,int>m;int GCD(int a, int b) {    return b==0?a:GCD(b, a%b);}int LCM(int a, int b) {    return a/GCD(a,b)*b;}LL dfs(int pos, int mod, int lcm, bool limit) {    if(!pos) return (mod%a[lcm]==0);    if(!limit&&dp[pos][mod][lcm]!=-1) return dp[pos][mod][lcm];    int len=(limit?digit[pos]:9);    LL ret=0LL;    for(int i=0; i<=len; ++i)        ret+=dfs(pos-1, (mod*10+i)%maxn, i==0?lcm:m[LCM(a[lcm],i)], limit&&i==len);    if(!limit) dp[pos][mod][lcm]=ret;    return ret;}LL work(LL x) {    int len=0;    while(x) digit[++len]=x%10, x/=10;    return dfs(len, 0, 0, true);}int main() {    memset(dp, -1, sizeof(dp));    for(int i=1; i<=maxn; ++i)        if(maxn%i==0) a[t]=i, m[i]=t++;    int T; cin>>T;    while(T--) {        LL a, b; cin>>a>>b;        cout<<work(b)-work(a-1)<<endl;    }    return 0;}

原创粉丝点击