1. 程式人生 > >快速冪_逆元_求組合數

快速冪_逆元_求組合數

快速冪:

遞迴形式:

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;
	}
}

山東省第八屆acm省賽d題HEX

原點的座標為(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;
	}

}