数位DP——HDU6148 Valley Number

题面:hdu6148
比赛的时候调到快结束的时候才A掉。。。(我真是太弱了。。。
其实就是数位DP,状态也很简单:
f[i][j][k] 表示i位数字开头数字为j,当前状态为k的数量,k=1表明已经有过递增,k=0表明没有过递增。。。
然后先把f求出来之后直接统计答案就行了
还是很简单的。。。要是早调出来几分钟说不定文化衫就有了呢QAQ

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
#define int long long
using namespace std;
const int MOD=1e9+7;
int f[1010][10][2];
char s[1010];
inline int dp(){
    scanf("%s",s+1);int l=strlen(s+1);
    if(l==1)return s[1]-'0';
    int ans=0;
    for(int i=1;i<l;i++)
        for(int j=1;j<10;j++)(ans+=f[i][j][0]+f[i][j][1])%=MOD;
    int flag=0;
    for(int i=1;i<l;i++){
        int now=s[i]-'0';
        for(int j=0;j<now;j++)if(i!=1||j!=0){
            if(flag==1&&j-s[i-1]+'0'<0)continue;
            (ans+=f[l-i+1][j][0])%=MOD;
            if((i==1)||(!flag&&j-s[i-1]+'0'<=0))(ans+=f[l-i+1][j][1])%=MOD;
        }        
        if((i>1)&&s[i]-s[i-1]<0&&flag){flag=2;break;}
        if((i>1)&&s[i]-s[i-1]>0)flag=1;
    }
    if(flag<2){
        int now=s[l]-'0';    
        if(flag<2)for(int j=0;j<=now;j++){
            if(flag==1&&j-s[l-1]+'0'<0)continue;
            (ans+=f[1][j][0])%=MOD;
        }
    }
    return ans;
}
signed main()
{
    for(int i=0;i<10;i++)f[1][i][0]=1;
    for(int i=2;i<=100;i++)
        for(int j=0;j<10;j++)
            for(int k=0;k<10;k++){
                if(j>k)(f[i][j][1]+=f[i-1][k][0]+f[i-1][k][1])%=MOD;
                if(j==k)(f[i][j][0]+=f[i-1][k][0],f[i][j][1]+=f[i-1][k][1])%=MOD;
                if(j<k)(f[i][j][0]+=f[i-1][k][0])%=MOD;
            }
    int T;scanf("%I64d",&T);
    while(T--)printf("%I64d\n",dp());
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值