【数位DP】HDU6148[Valley Number]题解

来源:互联网 发布:ipo 净利润 数据 编辑:程序博客网 时间:2024/05/21 22:48

题目概述

一个正整数是 Valley Number 需要满足没有任何一段数字出现先递增后递减(这里的递增和递减都不是严格的)的情况。

nValley Number 的数量。

解题报告

显然是数位DP,但是我刚开始想了一个很有病的定义,样例都没调出来TAT。

定义 f[i][j][t] 表示前 i 个数中第 i 个数是 j 且当前状态是 t0 :递减, 1 :递增)的方案数。

先预处理出 Sum(i) 表示长度为 1 ~ iValley Number 总数,然后我们只需要求长度为 Length(n)Valley Number 就行了。

示例程序

请读者老爷原谅我这么乱的代码(数位DP代码总是很乱),DP(L,R)表示求 f[L] ~ f[R]

#include<cstdio>#include<cstring>using namespace std;const int maxn=100,MOD=1000000007;int te,n,a[maxn+5],f[maxn+5][10][2],sum[maxn+5];#define Eoln(x) ((x)==10||(x)==13||(x)==EOF)int check(int k,int t,int j){    if (t) if (k>j) return -1; else return 1;    if (!t) if (k<j) return 1; else return 0;}void AMOD(int &x,int tem) {x+=tem;if (x>MOD) x-=MOD;}void DP(int L,int R){    for (int i=L;i<=R;i++)    for (int k=0;k<=9;k++)    for (int t=0;t<=1;t++) if (f[i-1][k][t])    for (int j=0;j<=9;j++)    {        int x=check(k,t,j);if (x==-1) continue;        AMOD(f[i][j][x],f[i-1][k][t]);    }}void Make(){    for (int i=1;i<=maxn;i++)    {        sum[i]=sum[i-1];memset(f,0,sizeof(f));        for (int j=1;j<=9;j++) f[1][j][0]=1;DP(2,i);        for (int j=0;j<=9;j++) AMOD(sum[i],f[i][j][0]),AMOD(sum[i],f[i][j][1]);    }}int main(){    freopen("program.in","r",stdin);    freopen("program.out","w",stdout);    for (Make(),scanf("%d",&te);te;te--)    {        char ch=getchar();while (Eoln(ch)) ch=getchar();        n=0;while (!Eoln(ch)) a[++n]=ch-48,ch=getchar();        int ans=sum[n-1];memset(f,0,sizeof(f));        for (int j=1;j<a[1];j++) f[1][j][0]=1;DP(2,n);        for (int j=0;j<=9;j++) AMOD(ans,f[n][j][0]),AMOD(ans,f[n][j][1]);        int fl=0;        for (int p=1;p<n;p++)        {            if (p>1) fl=check(a[p-1],fl,a[p]);if (fl==-1) break;            memset(f,0,sizeof(f));f[p][a[p]][fl]=1;            for (int j=0,x;j<a[p+1];j++) if (~(x=check(a[p],fl,j))) f[p+1][j][x]=1;            DP(p+2,n);for (int j=0;j<=9;j++) AMOD(ans,f[n][j][0]),AMOD(ans,f[n][j][1]);        }        if (~fl&&n>1) fl=check(a[n-1],fl,a[n]);if (~fl) AMOD(ans,1);        printf("%d\n",ans);    }    return 0;}
原创粉丝点击