百度之星复赛T5&&hdu6148

Problem Description

众所周知,度度熊非常喜欢数字。

它最近发明了一种新的数字:Valley Number,像山谷一样的数字。

当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再递增。在递增或递减的过程中可以出现相等的情况。

比如,1,10,12,212,32122都是 Valley Number。

121,12331,21212则不是。

度度熊想知道不大于N的Valley Number数有多少。

注意,前导0是不合法的。

Input

第一行为T,表示输入数据组数。

每组数据包含一个数N。

● 1≤T≤200

● 1≤length(N)≤100

Output

对每组数据输出不大于N的Valley Number个数,结果对 1 000 000 007 取模。

Sample input
3
3
14
120
Sample Output
3
14
119
——————————————————————————————
一道很明显的数位dp 然而写挂了很多次QAQ
f【i】【j】【k】【l】
表示考虑到第i位 这一位为j 此时是否开始上升 以及前l-1为是否和n(原数)相等
转移过程看代码吧QAQ 比较难讲 自己研究研究咯
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int mod=1e9+7,M=157;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int T,len,ans,h[M],f[M][15][2][2];
char s[M];
int calculate(int k){
    memset(f,0,sizeof(f));
    f[0][9][0][1]=1;
    for(int i=1;i<=k;i++){
        int now=s[i]-'0';
        for(int x=0;x<=9;x++){
            for(int y=(i==1)?1:0;y<=9;y++){
                for(int z=0;z<2;z++){
                    if(z&&y>now) continue;
                    int nowf=(z&&y==now);
                    if(x>=y){
                        if(x==y) f[i][y][1][nowf]=(f[i][y][1][nowf]+f[i-1][x][1][z])%mod;
                        f[i][y][0][nowf]=(f[i][y][0][nowf]+f[i-1][x][0][z])%mod;
                    }
                    else{
                        f[i][y][1][nowf]=(f[i][y][1][nowf]+f[i-1][x][1][z])%mod;
                        f[i][y][1][nowf]=(f[i][y][1][nowf]+f[i-1][x][0][z])%mod;
                    }
                }
            }
        }
    }
    int sum=0;
    for(int x=0;x<=9;x++) for(int y=0;y<2;y++) for(int z=0;z<2;z++) sum=(sum+f[k][x][y][z])%mod;
    return sum;
}
void prepare(){
    for(int i=1;i<=100;i++) s[i]='9';
    for(int i=1;i<=100;i++) h[i]=calculate(i);
}
int main()
{
    prepare();
    T=read();
    while(T--){
        ans=0;
        scanf("%s",s+1); len=strlen(s+1);    
        for(int i=1;i<len;i++) ans=(ans+h[i])%mod;
        ans=(ans+calculate(len))%mod;
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2017-08-18 20:14  友人Aqwq  阅读(171)  评论(0编辑  收藏  举报