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位有趣数为字集
(写代码过程)
第一次运行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
第二次运行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 //排列组合?
数位DP,
我以为0出现过就可以出现1呢。即010可以,其实错误。
(扩展)
没太搞明白,时间,内存限制,打acm装逼时只知道1s是10^7左右 当代计算机1s计算达百万次