hdu 6148(数位dp)

来源:互联网 发布:手机淘宝账号注册流程 编辑:程序博客网 时间:2024/05/29 13:28

题意:找出小于等于n的一直递增或者一直递减或者先递减后递增的数的个数。0不算。


思路:用两个flag分别标记F是否出现了递减和递增,然后直接进行就行。


PS:刚开始打百度之星复赛的时候交上去总是WA,赛后跟过了的队友对拍数据都没有错,GG,但总是过不去。

今天重打一遍之后,AC了。


#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> P;#define fi first#define se second#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x)#define PI acos(-1.0)const int Mod = 1e9 + 7;const int maxn = 100 + 10;char s[maxn];int bits[maxn];ll dp[maxn][10][2][2];ll dfs(int pos,bool lead,bool flag1,bool flag2,int pre,bool flag){    if(pos < 0){if(lead && pre == 0)return 0;return 1;}    if(!flag && !lead && dp[pos][pre][flag1][flag2] != -1)return dp[pos][pre][flag1][flag2];    int up = flag ? bits[pos] : 9;ll ret = 0;    for(int i = 0; i <= up; i ++)    {        if(flag2 && i >= pre)ret = (ret + dfs(pos - 1,lead && i == 0,flag1,flag2,i,flag && i == up)) % Mod;        else if(flag1 && !flag2)            ret = (ret + dfs(pos - 1,lead && i == 0,flag1,i > pre ? true : false,i,flag && i== up)) % Mod;        else if(!flag1 && !flag2)        {            bool t1 = false,t2 = false;            if(!lead && i > pre)t2 = true;else if(!lead && i < pre)t1 = true;            ret = (ret + dfs(pos - 1,lead && i == 0,t1,t2,i,flag && i == up)) % Mod;        }    }    if(!lead && !flag)dp[pos][pre][flag1][flag2] = ret;    return ret;}ll calc(){    int len = 0;for(int i = strlen(s) - 1;i >= 0; i --)bits[len ++] = s[i] - '0';    return dfs(len - 1,true,false,false,-1,true);}int main(){    clr(dp,-1);    int Tcase;scanf("%d",&Tcase);    while(Tcase --)    {        scanf("%s",s);printf("%I64d\n",calc());    }    return 0;}


原创粉丝点击