码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 55D Beautiful numbers (树形DP)

时间:2015-01-19 22:47:04      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:acm   c语言   编程   数位dp   算法   

          想了半天,总算想出来了。这题刚上来的思路很明显是11维DP。。但是明显不可取。。

         这题的关键在于只要两个数前面的拥有的数字是一样的,而且此时与其最小公倍数的模是一样的,那么这时候就可以认为对所有的数字取模都是相等的,那么后面的总情况数属于完美数的情况也是相同的。

         只要想到这步的话,那么基本思路就出来了,我第一次居然脑残的记录lcm与模2520(2到9的最小公倍数),首先lcm相同并不代表出现的数字相同先不说,仅仅这个最大值就太大了,lcm最大是2520,这样的话就需要开一个20*2520*2520的数组,我一看给的内存挺大的,就这么写了,然后提交。。果然MLE  on TEST 1.。。。

         然后才用的二进制状压记录2到9出现的数,因为0到1不用记录,所以只需要开1<<8大小就可以了。

这样空间复杂度就少了很多。然后就这样一改,果然AC了。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
const int mod=2520;
const int INF=0x3f3f3f3f;
const double eqs=1e-8;
LL dp[19][257][2530], c[20], lcm[257];
int gcd(int x, int y)
{
    return y==0?x:gcd(y,x%y);
}
int getlcm(int x, int y)
{
    if(!x) return y;
    return x*y/gcd(x,y);
}
int find1(int x, int y)
{
    if(y<=1) return x;
    y-=2;
    if(x&(1<<y)) return x;
    return x|(1<<y);
}
int init()
{
    int ans=1;
    int i, j;
    lcm[0]=1;
    for(i=1;i<=255;i++){
        ans=1;
        for(j=2;j<=9;j++){
            if(i&(1<<(j-2))){
                ans=getlcm(ans,j);
            }
        }
        lcm[i]=ans;
    }
}
LL dfs(int cnt, int maxd, int zero, int z, int mods)
{
    if(cnt==-1) return !(mods%lcm[z]);
    if(zero&&maxd&&dp[cnt][z][mods]!=-1) return dp[cnt][z][mods];
    int i, r=maxd?9:c[cnt];
    LL ans=0;
    for(i=0;i<=r;i++){
            ans+=dfs(cnt-1,maxd||i<r,zero||i,find1(z,i),(mods*10+i)%mod);
        }
    if(zero&&maxd) dp[cnt][z][mods]=ans;
    return ans;
}
LL Cal(LL x)
{
    int i, cnt=0;
    while(x){
        c[cnt++]=x%10;
        x/=10;
    }
    return dfs(cnt-1,0,0,0,0);
}
int main()
{
    int t;
    LL l, r;
    memset(dp,-1,sizeof(dp));
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%I64d%I64d",&l,&r);
        printf("%I64d\n",Cal(r)-Cal(l-1));
    }
    return 0;
}


CodeForces 55D Beautiful numbers (树形DP)

标签:acm   c语言   编程   数位dp   算法   

原文地址:http://blog.csdn.net/scf0920/article/details/42881393

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!