2011年6月8日晚7点,参加了【SRM 509 DIV 1】
250P:全场75分钟一直在做这题,一开始想位运算枚举肯定会超时,就想其他方案了,可样例总是不能全通过,本想放弃了,但还是坚持了下来,最后6分钟才提交,后又发现组合数组C[][]使用int会溢出应该用long,重新提交一次,最后几十秒发现大数应该先模9再乘积,否则两大数相乘又会溢出,又重新提交一次。
Challenge阶段,没人cha我的,自认为自己的代码肯定是对的,最后居然没有通过System Test,好奇怪,后来反应过来50位的数用long型也不行啊^_^
250P Problem
一个由'1'-'9'组成的字符串,最大长度为50。
For example, if X is 123, then super(X) = 123 + 12 + 13 + 23 + 1 + 2 + 3 = 177.
求super(X)%9.
250P Solution
来自论坛解释
First notice that
a number mod 9 is the sum of the digits in the number mod 9.
Next notice that
every digit appears 2^(n-1) times in different subsets, like for 123: {1,2,3}, {1,2}, {1,3}, {2,3}, {1}, {2}, {3}.
The answer is therefore 2^(n-1)*digitSum (mod 9).
public class LuckyRemainder {
public int getLuckyRemainder(String X) {
int p2 = 1;
for (int i = 1; i < X.length(); i++) {
p2 = (p2 * 2) % 9;
}
int res = 0;
for (char c : X.toCharArray()) {
res += c - '0';
}
return (res * p2) % 9;
}
}
我的代码,如果改为大数(BigInteger)应该可以AC的,C[k][i]:从k个数里选择i个数的可行数
public class LuckyRemainder {
int[] A;
int len;
long res;
long[][] C = new long[51][51]; // resubmit
public int getLuckyRemainder(String X) {
len = X.length();
A = new int[len];
for(int i = 0; i < len; i++)
A[i] = X.charAt(i) - '0';
C[0][0] = C[1][0] = C[1][1] = 1;
for(int i = 2; i < 51; i++) {
for(int j = 0; j <= i; j++) {
if(j == 0 || j == i)
C[i][j] = 1;
else
C[i][j] = C[i-1][j] + C[i-1][j-1];
}
}
res = 0;
for(int i = 0; i < len; i++) {
solve(i);
}
return (int)res;
}
void solve(int i) {
int k = len-1-i;// i位置右边最多有几位
int kk = len-1-k;// i位置左边最多有几位
for(int j = k; j >= 0; j--) {
for(int jj = kk; jj >= 0; jj--) {
long v = A[i];
for(int m = 0; m < j; m++)
v *= 10; // Failed Reason:if j=49...
res = (res+(v%9)*(C[k][j]%9)*(C[kk][jj]%9))%9; // resubmit
}
}
}
}