快速幂_逆元_求组合数

快速幂:

递归形式:

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

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值