快速冪_逆元_求組合數
阿新 • • 發佈:2018-11-05
快速冪:
遞迴形式:
static long pow_mod(long a, long n) {
if (n == 0) {
return 1;
}
long x = pow_mod(a, n / 2);
long ans = x * x % MOD;
if ((n & 1) == 1) {
ans = ans * a % MOD;
}
return ans;
}
非遞迴形式:
static long pow_mod(long a, long n) { long ans = 1; while (n > 0) { if ((n & 1) == 1) { ans = ans * a % MOD; } a = a * a % MOD; n >>= 1; } return ans; }
階乘打表:
static long arr[] = new long[100010];
static int MOD = 1000000007;
public static void Init() {
arr[0] = arr[1] = 1;
for (int i = 2; i <= 1e5; i++) {
arr[i] = (arr[i - 1] * i) % MOD;
}
}
逆元求組合數:
static long cn(int n, int m) { return ((arr[n] * pow_mod(arr[(n - m)], MOD - 2)) % MOD * pow_mod(arr[m], MOD - 2)) % MOD; }
山東省第八屆acm省賽c題 fireworks
(數學好啊、偷偷的抹一把淚)import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer; public class C { static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); static int nextInt() throws IOException { in.nextToken(); return (int) in.nval; } static String next() throws IOException { in.nextToken(); return (String) in.sval; } static long arr[] = new long[100010]; static int MOD = 1000000007; public static void main(String[] args) throws IOException { int n, t, w; Init(); while (in.nextToken() != StreamTokenizer.TT_EOF) { n = (int) in.nval; t = nextInt(); w = nextInt(); long ans = 0; while (n-- > 0) { int c, x; x = nextInt(); c = nextInt(); int k = Math.abs(w - x); if ((k & 1) == (t & 1) && k <= t) { // 奇偶相同(楊輝三角性質),而且在時間範圍內,(一直向終點走可以到達、) ans = (ans + (c * cn(t, (k + t) / 2)) % MOD) % MOD; } } out.println(ans); out.flush(); } } public static void Init() { // 階乘打表 arr[0] = arr[1] = 1; for (int i = 2; i <= 1e5; i++) { arr[i] = (arr[i - 1] * i) % MOD; } } static long pow_mod(long a, long n) { // 快速冪、 if (n == 0) { return 1; } long x = pow_mod(a, n / 2); long ans = x * x % MOD; if ((n & 1) == 1) { ans = ans * a % MOD; } return ans; } static long pow_mod1(long a, long n) { // 快速冪、 long ans = 1; while (n > 0) { if ((n & 1) == 1) { ans = ans * a % MOD; } a = a * a % MOD; n >>= 1; } return ans; } static long cn(int n, int m) { // 求組合數、 return ((arr[n] * pow_mod(arr[(n - m)], MOD - 2)) % MOD * pow_mod(arr[m], MOD - 2)) % MOD; } }
原點的座標為(1,1),我們來分析一下、假設當前座標為(x,y)
那麼向左走一步,座標變為(x + 1,y)
向下走一步,座標變為(x + 2,y + 1)
向右走一波,左邊變為(x + 1, y + 1)
那麼從(1,1)->(x, y)
我們求的就是 向左走a步、向下走b步、向右走c步
有(1,1) + a *(1,0) + b (2,1) + c(1,1) == (x, y)
1 + a + 2 * b + c = x ①
1 + b + c = y ②
進行整理有:
a + b = x - y (① - ②)
b + c = y - 1(②移動位置)
因為x, y是直接輸入的、
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class D {
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
static String next() throws IOException {
in.nextToken();
return (String) in.sval;
}
static long arr[] = new long[100010];
static long f[] = new long[100010];
static int MOD = 1000000007;
public static void main(String[] args) throws IOException {
int x, y;
long ans = 0;
Init();
while (in.nextToken() != StreamTokenizer.TT_EOF) {
ans = 0;
x = (int) in.nval;
y = nextInt();
int t = x - y; // a + b
int k = y - 1; // b + c
int u = Math.min(t, k);
for (int i = 0; i <= u; i++) { // 列舉 b 的所有可能走法、 (i 相當於 b)
int a = t - i;
int c = k - i;
ans += cn(i + a + c, a) * cn(i + c, i) % MOD; // C(a + b + c, a) * C(b + c, b) * C(c, c)
ans %= MOD;
}
out.println(ans);
out.flush();
}
}
public static void Init() { // 階乘打表
arr[0] = arr[1] = 1;
for (int i = 2; i <= 1e5; i++) {
arr[i] = (arr[i - 1] * i) % MOD;
}
for(int i = 99999; i >= 0; i--) {
f[i] = pow_mod(arr[i], MOD - 2) % MOD;
}
}
static long pow_mod(long a, long n) { // 快速冪、
if (n == 0) {
return 1;
}
long x = pow_mod(a, n / 2);
long ans = x * x % MOD;
if ((n & 1) == 1) {
ans = ans * a % MOD;
}
return ans;
}
static long cn(int n, int m) { // 求組合數、
if (n == m || m == 0)
return 1;
return ((arr[n] *f[n - m]) % MOD * f[m]) % MOD;
}
}