有趣的数

http://blog.csdn.net/pipisorry/article/details/39434559

时间限制: 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


code:(时间复杂度过高,TLE)

//*******************************************************************/
//*		CCF软件能力认证考试模拟题 —— 有趣的数	皮皮 2014-9-20		*/
//*******************************************************************/
#include <assert.h>
#include <stdio.h>
#include <set>
using namespace std;

static int digit;
static int count = 0;
static multiset<int> set_num;
/*	回溯法	TLE	20分	*/
static void funnyNum(int deepth){										//deepth从0开始
	if(deepth >= digit){										//已找到一条路径(解)
																//0, 1, 2, 3四个数字都出现过至少一次
		if( set_num.find(0) != set_num.end() && set_num.find(1) != set_num.end() && set_num.find(2) != set_num.end() &&set_num.find(3) != set_num.end()){
			count++;
			count %= 1000000007;
		}
	}else{
		if(deepth == 0){
			for(int i = 1; i <= 3; i++){						//第deepth+1位上的数字
				set_num.insert(i);
				funnyNum(deepth + 1);
				set_num.erase(set_num.find(i));					//回溯时erase掉
			}
		}else{
			for(int i = 0; i <= 3; i++){
				if(i == 0 && set_num.find(1) == set_num.end()){	//前面位置上有1则当前位置上不能是0
					set_num.insert(0);
					funnyNum(deepth + 1);
					set_num.erase(set_num.find(0));
				}else if(i == 2 && set_num.find(3) == set_num.end()){
					set_num.insert(2);
					funnyNum(deepth + 1);
					set_num.erase(set_num.find(2));
				}else if( i== 1 || i == 3){
					set_num.insert(i);
					funnyNum(deepth + 1);
					set_num.erase(set_num.find(i));
				}
			}
		}
	}
}

int main(){
	//assert( freopen("ccf\\FunnyNum.in", "r", stdin) );

	scanf("%d", &digit);
	funnyNum(0);
	printf("%d\n", count);

	//fclose(stdin);
	return 0;
}
from: http://blog.csdn.net/pipisorry/article/details/39434559


评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值