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, T. T 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
2
5
6
Output
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));
}
}