码迷,mamicode.com
首页 > 其他好文 > 详细

『8.21 模拟赛』Victory

时间:2018-08-21 21:12:52      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:代码   out   const   ==   题目   har   for   def   pac   

题目描述

迟到大王rsw喜欢V这个字母,因为V代表着victory,当一个数字,从左向右数的时候,没有出现过先递减,再递增的情况,就被称作Victory数。

也就是说,这个数字可以是递增的,也可以是递减的,也可以是先递减再递增的,这个过程中可以出现相邻数字相等的情况,但是,就是不能出现过先递减再递增的情况。

问题是:给定n,问:1~n之间有多少个victory数。





解题思路

我们应该一眼就能看出这是一道数位dp题,一开始用3维dp写,状态不够写挂了。。。后来改用4维就A了。

我们用dp[ i ][ j ][ k ][ l ] 来表示当前选到了第i位,当前选择的数是j,\(k=0\)表示当前的状态是递增的,\(k=1\)表示当前的状态是递减的,\(l=0\)表示当前没有遇到上界,\(l=1\)表示当前遇到了上界。但是在转移的时候有很多的细节,所以我们要慢慢分析:

比如,上升和下降并不是严格的,所以我们一定要注意一下,比如还没有出现严格上升的时候的k一直等于1,也就是递减的,遇到了一次严格递增的我们就把k严格设置成0,这样我们就可以防止重复情况的计算。

我们dfs的时候一定要注意前导0对答案的影响:比如098是一个合法的三位数,但是我们很容易漏掉他,一开始在这挂了好久,我们从每一位开始枚举,注意枚举最高位的时候l的取值。





代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const LL MOD=1000000007;
char n[150];
int len,a[150];
LL dp[102][11][2][2];
inline LL dfs(int wei,int num,bool ud,bool flag){
    if(wei==1)return 1;
    if(dp[wei][num][ud][flag])return dp[wei][num][ud][flag];
    if(ud==0){
        if(flag){
            for(register int i=num;i<=a[wei-1];i++){
                if(i==a[wei-1]){
                    dp[wei][num][ud][flag]+=dfs(wei-1,i,ud,1);
                    dp[wei][num][ud][flag]%=MOD;
                }
                else {
                    dp[wei][num][ud][flag]+=dfs(wei-1,i,ud,0);
                    dp[wei][num][ud][flag]%=MOD;
                }
            }
        }
        else {
            for(register int i=num;i<=9;i++){
                dp[wei][num][ud][flag]+=dfs(wei-1,i,ud,0);
                dp[wei][num][ud][flag]%=MOD;
            }
        }
        return dp[wei][num][ud][flag];
    }
    else {
        if(flag){
            for(register int i=0;i<=min(num,a[wei-1]);i++){
                if(i==a[wei-1]){
                    dp[wei][num][ud][flag]+=dfs(wei-1,i,ud,1);
                    dp[wei][num][ud][flag]%=MOD;
                }
                else {
                    dp[wei][num][ud][flag]+=dfs(wei-1,i,ud,0);
                    dp[wei][num][ud][flag]%=MOD;
                }
            }
            for(register int i=num+1;i<=a[wei-1];i++){
                if(i==a[wei-1]){
                    dp[wei][num][ud][flag]+=dfs(wei-1,i,0,1);
                    dp[wei][num][ud][flag]%=MOD;
                }
                else {
                    dp[wei][num][ud][flag]+=dfs(wei-1,i,0,0);
                    dp[wei][num][ud][flag]%=MOD;
                }
            }
        }
        else {
            for(register int i=0;i<=num;i++){
                dp[wei][num][ud][flag]+=dfs(wei-1,i,1,0);
                dp[wei][num][ud][flag]%=MOD;
            }
            for(register int i=num+1;i<=9;i++){
                dp[wei][num][ud][flag]+=dfs(wei-1,i,0,0);
                dp[wei][num][ud][flag]%=MOD;
            }
        }
        return dp[wei][num][ud][flag];
    }
}
int main(){
    scanf("%s",n+1);
    len=strlen(n+1);
    for(register int i=1;i<=len;i++){
        a[len+1-i]=(int)(n[i]-'0');
    }
    LL ans=0;
    for(register int i=1;i<=a[len];i++){
        if(i!=a[len])ans+=dfs(len,i,1,0);
        else ans+=dfs(len,i,1,1);
        ans%=MOD;
    }
    for(register int i=len-1;i>=1;i--){
        memset(dp,0,sizeof(dp));
        for(register int j=1;j<=9;j++){
            ans+=dfs(i,j,1,0);
            ans%=MOD;
        }
    }
    cout<<ans<<endl;
}

『8.21 模拟赛』Victory

标签:代码   out   const   ==   题目   har   for   def   pac   

原文地址:https://www.cnblogs.com/Fang-Hao/p/9513777.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!