CCF 有趣的数

问题描述

试题编号: 201312-4
试题名称: 有趣的数
时间限制: 1.0s
内存限制: 256.0MB
问题描述
问题描述
  我们把一个数称为有趣的,当且仅当:
  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

题目大意:

解题思路:

附录:

(审题过程)

读题后10min之内一度以为是不是题目不严谨,n位是不是都是一样的,比如1个0,2个1,2个2,1个3组成多少种有趣数?再一想不对,应该是用递归的角度来思考,n位的话,遍历第一位是什么,第二位什么......即可以混合。

递归所求(题目答案)为全集,而无数种相同n位有趣数为字集

(写代码过程)

第一次运行

 1 //dfs(x){for(0 n)for(0 4)}
 2 //
 3 //dfs(x, n)
 4 //
 5 //fx(x)for(0 n)for(0 4)
 6 // 7 //养成好习惯,先想再码
 8 #include<cstdio>
 9 int n;
10 void dfs(bool canbe_1, bool canbe_3, int No);//No表示该在哪个位置填入数字,从0开始
11 char number[1050];
12 char box[4] = {0, 1, 2, 3};//填入什么数字从这四个中选
13 int answer;
14 int main()
15 {
16     scanf("%d", &n);
17     dfs(0, 0, 0);
18 //    printf("%d%1000000007", answer);
19     printf("%d", answer);
20 }
21 void dfs(bool canbe___1, bool canbe___3, int No)
22 {
23     if(No == n + 1){
24         answer ++;
25         return;
26     }
27     for(int i = 0; i < 4; i ++)
28     {
29 //        if()//这里是先判断No还是先判断i
30         if(i == 0){
31             if(No == 0)
32                 continue;
33             else{
34                 number[No] = box[i];
35                 canbe___1 = 1;
36                 dfs(canbe___1, canbe___3, No ++);
37             }
38         }
39         else if(i == 1){
40             if(!canbe___1)
41                 continue;
42             else{
43                 number[No] = box[i];
44                 dfs(canbe___1, canbe___3, No ++);
45             }
46         }
47         else if(i == 2){
48             number[No] = box[i];
49             canbe___3 = 1;
50             dfs(canbe___1, canbe___3, No ++);
51         }
52         else if(i == 3){
53             if(!canbe___3)
54                 continue;
55             else{
56                 number[No] = box[i];
57                 dfs(canbe___1, canbe___3, No ++);
58             }
59         }
60     }
61 }
62 
63 //No. !=0
64 //0 1
65 //2 3
66 //
67 //2013
68 //2031
69 //2301
70 //
71 //0   0123
72 //1   0123
73 //2   0123
74 //3   0123
View Code

 第二次运行

 1 #include<cstdio>
 2 int n;
 3 void dfs(bool canbe_1, bool canbe_3, int No);//No表示该在哪个位置填入数字,从0开始
 4 char number[1050];
 5 char box[4] = {0, 1, 2, 3};//填入什么数字从这四个中选
 6 int answer;
 7 int main()
 8 {
 9     scanf("%d", &n);
10     dfs(0, 0, 0);
11     printf("%d", answer);
12 }
13 void dfs(bool canbe___1, bool canbe___3, int No)
14 {
15     if(No == n){
16         answer ++;
17         return;
18     }
19     for(int i = 0; i < 4; i ++){
20 //        if()//这里是先判断No还是先判断i
21         if(i == 0){
22             if(No == 0)
23                 continue;
24             else{
25                 number[No] = box[i];
26                 canbe___1 = 1;
27                 dfs(canbe___1, canbe___3, No ++);
28             }
29         }
30         else if(i == 1){
31             if(!canbe___1)
32                 continue;
33             else{
34                 number[No] = box[i];
35                 dfs(canbe___1, canbe___3, No ++);
36             }
37         }
38         else if(i == 2){
39             printf("##");
40             number[No] = box[i];
41             canbe___3 = 1;
42             dfs(canbe___1, canbe___3, No ++);
43         }
44         else if(i == 3){
45             if(!canbe___3)
46                 continue;
47             else{
48                 number[No] = box[i];
49                 dfs(canbe___1, canbe___3, No ++);
50             }
51         }
52     }
53 }
54 
55 //0 1
56 //2 3
57 
58 //2013
59 //2031
60 //2301
61 
62 dfs 011
63 2
64 20
65 dfs 112
66 200
67 
68 //这四个数字都出现过至少一次
69 20133//先0123再重复
70 20013//直接前四位中就有重复
71 
72 //卡住了。“这四个数字都出现过至少一次”,不知道怎么写。
73 
74 2 _ _ _ _ _
75   3 
76 //排列组合?
View Code

 

数位DP,

我以为0出现过就可以出现1呢。即010可以,其实错误。

(扩展)

没太搞明白,时间,内存限制,打acm装逼时只知道1s是10^7左右 当代计算机1s计算达百万次

 

原文地址:https://www.cnblogs.com/gerjcs/p/12901746.html