HDU 5179 beautiful number 数位DP(水)

来源:互联网 发布:雨滴桌面上的软件 编辑:程序博客网 时间:2024/05/21 05:40
HDU 5179
题意:x={a[1]a[2]a[2]..a[n]},a[1]为高位. 
定义一个数x合法,当a[i]>=a[i+1] && a[i]%a[j]==0(1<=i<=n,i<j<=n)
L,R<=1e9.问[L,R]有多少个数合法? 


假如最高位为y,a[1]=y 则后面所有的数都为a[1]的因子.
其实只要记录前面一个数是多少 后面一个数只要为它的因子即可.

数位DP套路:f[pos][pre] 还需要pos位 前一位为pre的方法数. 注意前导0(缺位时)特判即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=25;int a[N],dp[N][N];int dfs(int pos,int pre,bool flag,bool limit){    if(pos==0)        return flag==false;    if(!flag&&!limit&&dp[pos][pre]!=-1)        return dp[pos][pre];    int up=limit?a[pos]:9;    int res=0;    for(int i=0;i<=up;i++)    {        if(i==0&&flag)            res+=dfs(pos-1,i,true,false);        else if(flag||(i!=0&&i<=pre&&pre%i==0))            res+=dfs(pos-1,i,false,limit&&i==up);    }    if(!limit&&!flag)        dp[pos][pre]=res;    return res;}int solve(int n){    if(n==0)        return 0;    int pos=0;    while(n)    {        a[++pos]=n%10;        n/=10;    }    return dfs(pos,0,true,true);}int main(){    memset(dp,-1,sizeof(dp));    int T,L,R;    cin>>T;    while(T--)    {        scanf("%d%d",&L,&R);        printf("%d\n",solve(R)-solve(L-1));    }    return 0;}