zoukankan      html  css  js  c++  java
  • 有趣的数

    有趣的数

    问题描述

    我们把一个数称为有趣的,当且仅当:

    1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。

    2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。

    3. 最高位数字不为0。

    因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。

    请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。

    输入格式

    输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。

    输出格式

    输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。

    样例输入

    4

    样例输出

    3

    动态规划

    刚看到题的时候并没有什么想法,反正时间多,先暴力跑一下看看有没有规律= =

    暴力代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #define LL long long
     4 using namespace std;
     5 char s[1005];
     6 LL sum;
     7 int main(void){
     8     int n;
     9     scanf("%d",&n);
    10     LL a=1,b=3;
    11     for(int i=1;i<n;++i){
    12         a*=10;
    13         b=b*10+3;
    14     }
    15     while(a<=b){
    16         LL t=a;
    17         memset(s,0,sizeof(s));
    18         int k=0;
    19         while(t){
    20             s[k++]=t%10+'0';
    21             t/=10;
    22         }
    23         bool flag=1;
    24         int l1=-1,l2=-1,l3=-1,l0=-1;
    25         for(int i=0;i<=k;++i){
    26             if(s[i]>'3'){
    27                 flag=0;
    28                 break;
    29             }
    30             if(s[i]=='0'){
    31                 l0=i;
    32             }else if(s[i]=='1'){
    33                 if(l0!=-1){
    34                     flag=0;
    35                     break;
    36                 }
    37                 l1=i;
    38             }else if(s[i]=='2'){
    39                 l2=i;
    40             }else if(s[i]=='3'){
    41                 if(l2!=-1){
    42                     flag=0;
    43                     break;
    44                 }
    45                 l3=i;
    46             }
    47         }
    48         if(flag){
    49             if(l0!=-1&&l1!=-1&&l2!=-1&&l3!=-1){
    50                 sum++;
    51             }
    52         }
    53         a++;
    54     }
    55     printf("%lld
    ",sum);
    56     return 0;
    57 }
    View Code

    试了几个数据,尼玛n=9的时候就跑不动了QAQ,没找到什么规律,开始想其他解法。

    考虑到01串与23串的取法分别独立,当01的总位数为a时,有a-1种方案,12的总位数为b时,有b-1种方案。而题目中所要求的也就可以转变为将a位的01插入到b位的23中共有几种插法,也就是a个球放到b个箱子有几种方案。定义状态dp[i,j]为i个球放j个盒子的方案数,然后有dp[i,j]=1+dp[1,j-1]+dp[2,j-1]+dp[3,j-1]+...+dp[i,j-1];但是如此的话复杂度为O(n^3),对于数据规模10^3肯定会爆...

    O(n^3)代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #define LL long long
     4 #define N 1000
     5 #define Mod 1000000007
     6 using namespace std;
     7 LL dp[N][N];
     8 int main(void){
     9     for(int i=1;i<N;++i){
    10         dp[1][i]=i;
    11         dp[i][1]=1;
    12     }
    13     for(int i=2;i<N;++i){
    14         for(int j=2;j<N;++j){
    15             LL t=1;
    16             for(int k=1;k<=i;++k){
    17                 t=(t+dp[k][j-1])%Mod;
    18             }
    19             dp[i][j]=t;
    20         }
    21     }
    22 
    23     int n;
    24     scanf("%d",&n);
    25     LL sum=0;
    26     for(int i=2;i<=n-2;++i){
    27         LL t=0;
    28         t=((((i-1)*(n-i-1))%Mod)*dp[i][n-i])%Mod;
    29         sum=(sum+t)%Mod;
    30     }
    31     printf("%lld
    ",sum);
    32     return 0;
    33 }
    View Code

    纠结了一番发现dp[i,j]=dp[i-1,j]+dp[i,j-1]这样一来复杂度就变为了O(n^2),对于n<1000的数据就轻松过了hhh.

    代码如下:

     1 #include<cstdio>
     2 #include<cstring>
     3 #define LL long long
     4 #define N 1000
     5 #define Mod 1000000007
     6 using namespace std;
     7 LL dp[N][N];
     8 int main(void){
     9     for(int i=1;i<N;++i){
    10         dp[1][i]=i;
    11         dp[i][1]=1;
    12     }
    13     for(int i=2;i<N;++i){
    14         for(int j=2;j<N;++j){
    15             dp[i][j]=(dp[i-1][j]+dp[i][j-1])%Mod;
    16         }
    17     }
    18 
    19     int n;
    20     scanf("%d",&n);
    21     LL sum=0;
    22     for(int i=2;i<=n-2;++i){
    23         LL t=0;
    24         t=((((i-1)*(n-i-1))%Mod)*dp[i][n-i])%Mod;
    25         sum=(sum+t)%Mod;
    26     }
    27     printf("%lld
    ",sum);
    28     return 0;
    29 }
  • 相关阅读:
    ubuntu18.04LTS服务器用vituralenv安装和配置pytorch和tensorflow
    ubuntu18.04安装Anaconda
    XeLaTeX下如何以原大小显示PNG
    JS黑魔法之this, setTimeout/setInterval, arguments
    sicily 1198. Substring (递归全排列+排序)
    sicily 1046. Plane Spotting(排序求topN)
    sicily 1051. Biker's Trip Odomete
    sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)
    sicily 1035. DNA matching
    关于组织自定义皮肤/主题的一点思考
  • 原文地址:https://www.cnblogs.com/barrier/p/5612528.html
Copyright © 2011-2022 走看看