历届试题 公式求值
时间限制:1.0s 内存限制:256.0MB
问题描述
输入n, m, k,输出下面公式的值。
其中C_n^m是组合数,表示在n个人的集合中选出m个人组成一个集合的方案数。组合数的计算公式如下。
其中C_n^m是组合数,表示在n个人的集合中选出m个人组成一个集合的方案数。组合数的计算公式如下。
输入格式
输入的第一行包含一个整数n;第二行包含一个整数m,第三行包含一个整数k。
输出格式
计算上面公式的值,由于答案非常大,请输出这个值除以999101的余数。
样例输入
3
1
3
1
3
样例输出
162
样例输入
20
10
10
10
10
样例输出
359316
数据规模和约定
对于10%的数据,n≤10,k≤3;
对于20%的数据,n≤20,k≤3;
对于30%的数据,n≤1000,k≤5;
对于40%的数据,n≤10^7,k≤10;
对于60%的数据,n≤10^15,k ≤100;
对于70%的数据,n≤10^100,k≤200;
对于80%的数据,n≤10^500,k ≤500;
对于100%的数据,n在十进制下不超过1000位,即1≤n<10^1000,1≤k≤1000,同时0≤m≤n,k≤n。
对于20%的数据,n≤20,k≤3;
对于30%的数据,n≤1000,k≤5;
对于40%的数据,n≤10^7,k≤10;
对于60%的数据,n≤10^15,k ≤100;
对于70%的数据,n≤10^100,k≤200;
对于80%的数据,n≤10^500,k ≤500;
对于100%的数据,n在十进制下不超过1000位,即1≤n<10^1000,1≤k≤1000,同时0≤m≤n,k≤n。
提示
999101是一个质数;
当n位数比较多时,绝大多数情况下答案都是0,但评测的时候会选取一些答案不是0的数据;
当n位数比较多时,绝大多数情况下答案都是0,但评测的时候会选取一些答案不是0的数据;
Java源代码:
1 import java.math.BigInteger; 2 import java.util.Scanner; 3 4 public class Main { 5 public static BigInteger lucas(BigInteger n, BigInteger m, BigInteger p) { 6 if (m.equals(BigInteger.ZERO)) 7 return BigInteger.ONE; 8 return BigInteger 9 .valueOf(f(n.mod(p).longValue(), m.mod(p).longValue())) 10 .multiply(lucas(n.divide(p), m.divide(p), p)).mod(p); 11 } 12 13 public static long f(long n, long m) { 14 if (m > n) 15 return 1; 16 if (n == m || m == 0) 17 return 1; 18 if (m > n - m) 19 m = n - m; 20 long tmpi = 1, tmpn = 1, s1 = 1, s2 = 1, ans = 1; 21 for (int i = 1; i <= m; i++) { 22 tmpi = i; 23 tmpn = n - i + 1; 24 s1 = s1 * tmpi % 999101; 25 s2 = s2 * tmpn % 999101; 26 } 27 ans = s2 * pow1(s1, 999099) % 999101; 28 return ans % 999101; 29 } 30 31 public static long pow1(long x, long n) { 32 if (x == 1) 33 return 1; 34 if (n == 0) 35 return 1; 36 else { 37 while ((n & 1) == 0) { 38 n >>= 1; 39 x = (x * x) % 999101; 40 } 41 } 42 long result = x % 999101; 43 n >>= 1; 44 while (n != 0) { 45 x = (x * x) % 999101; 46 ; 47 if ((n & 1) != 0) 48 result = result * x % 999101; 49 n >>= 1; 50 } 51 return result; 52 } 53 54 public static void main(String[] args) { 55 Scanner sc = new Scanner(System.in); 56 BigInteger n = new BigInteger(sc.nextLine()); 57 BigInteger m = new BigInteger(sc.nextLine()); 58 int k = Integer.parseInt(sc.nextLine()); 59 BigInteger md = new BigInteger("999101"); 60 long Cnm = lucas(n, m, md).longValue() % 999101; 61 long sum = 0; 62 if (Cnm != 0) { 63 int[][] a = new int[k][k]; 64 int h = 1; 65 for (int i = 0; i < k; i++) { 66 for (int j = 0; j < k; j++) { 67 if (j >= h) 68 a[i][j] = 0; 69 else { 70 if (j == 0 || j == h - 1) 71 a[i][j] = 1; 72 else { 73 a[i][j] = (a[i - 1][j - 1] * (h - j) + a[i - 1][j]) % 999101; 74 } 75 } 76 } 77 h++; 78 } 79 long m1 = 1, n1 = 1; 80 long x = n.subtract(new BigInteger(k + "")) 81 .mod(md.subtract(BigInteger.ONE)).longValue(); 82 long n3 = pow1(2, x); 83 for (int i = k - 1; i >= 0; i--) { 84 n1 = n3 * pow1(2, i) % 999101; 85 m1 = m1 86 * (n.subtract(new BigInteger((k - 1 - i) + "")).mod(md) 87 .longValue()) % 999101; 88 sum = (sum + m1 * a[k - 1][i] * n1) % 999101; 89 } 90 sum = sum * Cnm % 999101; 91 } 92 System.out.println(sum); 93 } 94 95 }
评测点序号 | 评测结果 | 得分 | CPU使用 | 内存使用 | 下载评测数据 |
---|---|---|---|---|---|
1 | 正确 | 10.00 | 187ms | 23.37MB | 输入 输出 |
2 | 正确 | 10.00 | 171ms | 23.19MB | 输入 输出 |
3 | 正确 | 10.00 | 156ms | 23.46MB | 输入 输出 |
4 | 正确 | 10.00 | 202ms | 23.36MB | 输入 输出 |
5 | 正确 | 10.00 | 202ms | 23.15MB | 输入 输出 |
6 | 正确 | 10.00 | 187ms | 23.86MB | 输入 输出 |
7 | 正确 | 10.00 | 202ms | 23.94MB | 输入 输出 |
8 | 正确 | 10.00 | 327ms | 25.40MB | 输入 输出 |
9 | 正确 | 10.00 | 483ms | 30.19MB | 输入 输出 |
10 | 正确 | 10.00 | 436ms | 31.25MB | 输入 输出 |