HDU POJ 数位DP

预处理求出所有答案,再根据具体数字求解,模板性较强。

DP版要想方程,所以还是记忆化搜索版容易,就是枚举每一位。

http://blog.csdn.net/synapse7/article/details/21006265?utm_source=tuicoo的注释大概能懂。

递归版利用了bit从1计数,而参数按0计数。如

23则bit[1]=3,bit[2]=2,传len=2进去,然后for遍历bit[2]顺便把len-1递归下去,然后len=1时遍历bit[1]=3,继续传0进去,然后返回


HDU 3555 BOMB 不含49

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin)

ll dp[25][3];         //dp[i][j]:i长度j情况
//dp[i][0]  长度为i且不含49
//dp[i][1]  长度为i不含49但以9开头
//dp[i][2]  长度为i含49
int bit[25];
void init()
{
    CLR(dp,0);
    dp[0][0] = 1;
    for(int i=1;i<=20;i++)      //2^63次方在20位以内
    {
        dp[i][0] = dp[i-1][0]*10-dp[i-1][1];    //不含49*10-补上4组成的49
        dp[i][1] = dp[i-1][0];                  //补上9
        dp[i][2] = dp[i-1][2]*10+dp[i-1][1];    //已含49*10+补上4组成的49
    }
}
int main()
{
    //RE;
    int t;
    ll n;
    init();
    cin>>t;
    while(t--)
    {
        cin>>n;
        n++;
        int len = 0;
        ll ans = 0;
        while(n)
        {
            bit[++len] = n % 10;
            n /= 10;
        }
        bit[len+1] = 0;
        bool flag = false;
        for(int i=len;i>=0;i--)
        {
            ans += dp[i-1][2]*bit[i];     //低位含49的*该位数字
            if(flag)
                ans += dp[i-1][0]*bit[i];  //组成49后就+=低位*该位
            if(!flag && bit[i]>4)          //后一位是9,那么数字大于4的都包含49
                ans += dp[i-1][1];
            if(bit[i]==9 && bit[i+1]==4)    //组成49
                flag = true;
        }
        cout<<ans<<endl;
    }
}

递归版

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)  
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)  

#define lson i<<1,l,m
#define rson i<<1|1,m+1,r

const int maxn=25;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;

int bit[maxn];
ll dp[maxn][2][2];

ll dfs(int len,bool is4,bool ok49,bool ismax){
    if(len<=0)    return ok49?1:0;
    if(!ismax && dp[len][is4][ok49] != -1)    return dp[len][is4][ok49];
    int pmax = ismax ? bit[len] : 9;
    ll cnt = 0;
    for (int i = 0; i <= pmax; ++i){
        cnt += dfs(len - 1,i == 4,ok49 || (is4 && i == 9),ismax && i == pmax);
    }
    return ismax ? cnt : dp[len][is4][ok49] = cnt;
}
ll solve(ll n){
    int cnt=0;
    while(n){
        bit[++cnt]=n%10;
        n/=10;
    }
    return dfs(cnt,false,false,true);
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
    #endif
    ll a,t;
    memset(dp,-1,sizeof(dp));
    cin>>t;
    while(t--){
        cin>>a;
        cout<<solve(a)<<endl;
    }
    return 0;
}


HDU 2089 不要62 不含4和相邻62的

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define Q_CIN ios::sync_with_stdio(false)
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin)

int dp[10][3];
//dp[i][0]  长度为i,无不吉利且不以2开头
//dp[i][1]  长度为i,无但以2开头
//dp[i][2]  长度为i,有
int bit[10];
void init()
{
    CLR(dp,0);
    dp[0][0] = 1;
    for(int i=1;i<=10;i++)
    {
        dp[i][0] = dp[i-1][0]*9-dp[i-1][1]; //除4外的9个-后一位是2的情况
        dp[i][1] = dp[i-1][0];              //直接加2
        dp[i][2] = dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0]; //原有的+加6的+加4的
    }
}
int solve(int n)
{
    int len = 0;
    int ans = 0;
    int tmp = n;
    while(n)
    {
        bit[++len] = n % 10;
        n /= 10;
    }
    bit[len+1] = 0;
    bool flag = false;

    for(int i=len;i>=0;i--)
    {
        ans += dp[i-1][2]*bit[i];
        if(flag)
            ans += dp[i-1][0]*bit[i];
        if(!flag && bit[i]>6)
            ans += dp[i-1][1];
        if(!flag && bit[i]>2&&bit[i+1]==6)//62x
           ans += dp[i][1]; //dp[i][1]
        if(!flag && bit[i]>4)
            ans += dp[i-1][0];
        if((bit[i]==2 && bit[i+1]==6)||bit[i]==4)
            flag = true;
    }
    return tmp-ans; //求没有不吉利的
}
int main()
{
//    RE;
    int n,m;
    init();
    while(cin>>n>>m,m||n)
    {
        CLR(bit,0);
        cout<<solve(m+1)-solve(n)<<endl;    //[n,m]=[1,m]-[1,n)
    }
    return 0;
}



#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)  
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)  

#define lson i<<1,l,m
#define rson i<<1|1,m+1,r

const int maxn=10;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;

int bit[maxn];
int dp[maxn][2];

int dfs(int len,bool is6,bool ismax){
    if(len==0)    return 1;
    if(!ismax&&dp[len][is6]>=0)    return dp[len][is6];
    int cnt=0,pmax=(ismax?bit[len]:9);
    for (int i = 0; i <= pmax; ++i){
        if(i==4||(is6&&i==2))   continue;
        cnt+=dfs(len-1,i==6,ismax&&i==pmax);
    }
    return ismax?cnt:dp[len][is6]=cnt;
}
int solve(int n){
    int cnt=0;
    while(n){
        bit[++cnt]=n%10;
        n/=10;
    }
    return dfs(cnt,false,true);
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
    #endif
    int a,b;
    memset(dp,-1,sizeof(dp));
    while(cin>>a>>b,a||b){
        cout<<solve(b)-solve(a-1)<<endl;
    }
    return 0;
}


POJ 3252 Round Numbers

求[x,y]区间内“二进制表示0比1多的数”的个数。处理前导0,前导0不算0。
dp[len][num0][num1]:长度为len,0的数量为num0,1数量为num1的个数
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );

#define lson i<<1,l,m
#define rson i<<1|1,m+1,r

const int maxn=50;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;

int bit[maxn];
int dp[maxn][maxn][maxn];

int dfs(int len,int num0,int num1,bool first,bool ismax){
    if(len==0)    return num0>=num1?1:0;
    if(!ismax && dp[len][num0][num1] != -1)    return dp[len][num0][num1];
    int pmax = ismax ? bit[len] : 1;
    int cnt = 0;
    for (int i = 0; i <= pmax; ++i){
        if(first){
            if(i==0)
                cnt += dfs(len-1,0,0,true,ismax&&i==pmax);
            else
                cnt += dfs(len-1,0,1,false,ismax&&i==pmax);
        }else{
            if(i==0)
                cnt += dfs(len-1,num0+1,num1,false,ismax&&i==pmax);
            else
                cnt += dfs(len-1,num0,num1+1,false,ismax&&i==pmax);
        }
    }
    return ismax ? cnt : dp[len][num0][num1] = cnt;
}

int solve(int n){
    int cnt=0;
    while(n){
        bit[++cnt]=n%2;
        n/=2;
    }
    return dfs(cnt,0,0,true,true);
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
    #endif
    int a,t,b;
    memset(dp,-1,sizeof(dp));

    while(cin>>a>>b)
        cout<<solve(b)-solve(a-1)<<endl;
    return 0;
}

弱校OJ 233数

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;

#define lson i<<1,l,m
#define rson i<<1|1,m+1,r

const int maxn=50;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;

int bit[maxn];
ll dp[maxn][2][2][2];   //长度,是不是1,是不是23,是不是233

ll dfs(int len,bool is2,bool is23,bool ok,bool ismax){
    if(len<=0)    return ok?1:0;
    if(!ismax && (dp[len][is2][is23][ok] != -1))    return dp[len][is2][is23][ok];
    int pmax = ismax ? bit[len] : 9;
    ll cnt = 0;
    for (int i = 0; i <= pmax; ++i){
        cnt += dfs(len - 1,i==2,is2&&i == 3,ok||(is23&&i==3),ismax && i == pmax);
    }
    return ismax ? cnt : dp[len][is2][is23][ok] = cnt;
}
ll solve(ll n){
    int cnt=0;
    while(n>0){
        bit[++cnt]=n%10;
        n/=10;
    }
    return dfs(cnt,false,false,false,true);
}
int main()
{
    // #ifndef ONLINE_JUDGE
        // freopen("1.in","r",stdin);
        // freopen("1.out","w",stdout);
    // #endif
    ll a,t;
    memset(dp,-1,sizeof(dp));
    cin>>t;
    while(t--){
        cin>>a;
        cout<<solve(a)<<endl;
    }
    return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)  
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)  

#define lson i<<1,l,m
#define rson i<<1|1,m+1,r

const int maxn=20;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;

int bit[maxn];
ll dp[maxn][2][2][13]; //dp[i][j][k][k]:长度为i,是否以1结尾,有无13,模13的结果

ll dfs(int len,bool end1,bool have13,int mod,bool ismax){
    if(len==0)    return (!mod && have13);
    if(!ismax && (dp[len][end1][have13][mod] != -1))    return dp[len][end1][have13][mod];
    int pmax = ismax ? bit[len] : 9;
    ll cnt = 0;
    for (int i = 0; i <= pmax; ++i){
        int tmod = (mod*10+i) % 13;
        cnt += dfs(len-1,i==1,have13||(end1&&i==3),tmod,ismax && i == pmax);
    }
    return ismax ? cnt : dp[len][end1][have13][mod] = cnt;
}

ll solve(ll n){
    int cnt=0;
    while(n>0){
        bit[++cnt]=n%10;
        n/=10;
    }
    return dfs(cnt,false,false,0,true);
}
int main()
{
    ll a,t;
    memset(dp,-1,sizeof(dp));
    while(cin>>a){
        cout<<solve(a)<<endl;
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值