Code Jam 2010 Round 1B Problem C

Problem C. Your Rank is Pure

Problem

Pontius: You know, I like this number 127, I don't know why.
Woland: Well, that is an object so pure. You know the  prime numbers.
Pontius: Surely I do. Those are the objects possessed by our ancient masters hundreds of years ago. Oh, yes, why then? 127 is indeed a prime number as I was told.
Woland: Not... only... that. 127 is the 31st prime number; then, 31 is itself a prime, it is the 11th; and 11 is the 5th; 5 is the 3rd; 3, you know, is the second; and finally 2 is the 1st.
Pontius: Heh, that is indeed... purely prime.

The game can be played on any subset S of positive integers. A number in S is considered pure with respect to S if, starting from it, you can continue taking its rank in S, and get a number that is also in S, until in finite steps you hit the number 1, which is not in S.

When n is given, in how many ways you can pick S, a subset of {2, 3, ..., n}, so that n is pure, with respect to S? The answer might be a big number, you need to output it modulo 100003.

Input

The first line of the input gives the number of test cases, TT lines follow. Each contains a single integer n.

Output

For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the answer as described above.

Limits

T  ≤ 100.
Small dataset

2 ≤ n ≤ 25.

Large dataset

2 ≤ n ≤ 500.

Sample


Input 
 

Output 
 
2
5
6
Case #1: 5
Case #2: 8

解题思路:花了好多时间在理解题意上。前面讲质数什么的后面其实和质数一点关系也没有。理解之后就是组合问题了。对于某个N,根据S中元素个数计算出多组符合条件的情况,就会发现每一组个数计算的时候可以利用之前的结论。动态规划解决问题。

	long[][] memo = new long[501][501];
	long[][] c = new long[501][501];
	final long MOD = 100003;

	long calc(int n, int k) {
		if (memo[n][k] != -1) {
			return memo[n][k];
		}
		if (k == 1 || n - k == 1) {
			return memo[n][k] = 1;
		}

		memo[n][k] = 0;
		for (int j = 1; j < k; j++) {
			if (n - k >= k - j) {
				memo[n][k] = (memo[n][k] + calc(k, j) * c[n - k - 1][k - j - 1])
						% MOD;
			}
		}

		return memo[n][k];
	}

	void run() {
		for (long[] z : memo) {
			Arrays.fill(z, -1);
		}
		c[0][0] = 1;
		for(int i=1; i<501; i++){
			c[i][0] = 1;
			for(int j=1; j<501; j++){
				c[i][j] = (c[i-1][j-1] + c[i-1][j]) % MOD;
			}
		}
		int tests = sc.nextInt();
		for (int test = 1; test <= tests; test++) {
			int N = sc.nextInt();
			long ret = 0;
			for(int i=1; i<N; i++)
				ret = (ret + calc(N, i)) % MOD;
			System.out.println(String.format("Case #%d: %d", test, ret));
		}
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值