Combinatorial Mathematics DP Codeforces 722E

The meaning of problems: there is a n * m board, in your initial point (1, 1), you need to get to the point (n, m). You have s initial points, there are k points on the board, and after a fraction of this point will become s / 2 (rounded up), ask the mathematical expectation from the beginning to the end of the score is the number?

Ideas: according to routine, the k first point pair sorted manner, provided DP [i] [j] from the point prior to i through the j th least Save points, i is the mathematical expectation point. Then all transferred to it at the point it can be transferred to it before. Then dp [i] [j] = Σ (dp [u] [j - 1] - dp [u] [j]) * g (u, i). Where G (u, i) is the number of moves between u, i is no constraint condition, a combination of mathematical calculation method may be. This is equivalent to the foregoing points exactly + j through more than one point may be passed over the transfer mode, which can not be re-count is not guaranteed leak.

Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define db double
#define LL long long
#define pii pair<int, int>
using namespace std;
const int maxn = 200010;
const LL mod = 1e9 + 7;
LL dp[2010][40];
pii a[2010];
LL v[maxn], inv[maxn];
LL qpow(LL x, LL y) {
	LL ans = 1;
	for (; y; y >>= 1) {
		if(y & 1) ans = (ans * x) % mod;
		x = (x * x) % mod;
	}
	return ans;
}
void init(int n) {
	v[0] = 1;
	for (int i = 1; i <= n; i++) {
		v[i] = (v[i - 1] * i) % mod;
	}
	inv[n] = qpow(v[n], mod - 2);
	for (int i = n - 1; i >= 0; i--) {
		inv[i] = (inv[i + 1] * (i + 1)) % mod;
	}
}
LL C(LL n, LL m) {
	return (((v[n] * inv[m]) % mod) * inv[n - m]) % mod;
}
LL cal(int x, int y) {
	LL tmp = abs(a[y].first - a[x].first), tmp1 = tmp + (a[y].second - a[x].second);
	return C(tmp1, tmp);
}
LL b[50];
int main() {
	int n, m, k, t;
	scanf("%d%d%d%d", &n, &m, &k, &t);
	init(n + m);
	for (int i = 1; i <= k; i++) {
		scanf("%d%d", &a[i].first, &a[i].second);
	}
	int lim = 0;
	while(t > 1) {
		b[++lim] = t;
		t = (t + 1) / 2;
	}
	b[++lim] = 1;
	b[lim + 1] = 1;
	sort(a + 1, a + 1 + k);
	k++;
	a[k] = make_pair(n, m);
	for (int i = 1; i <= k; i++) {
		dp[i][0] = C(a[i].first + a[i].second - 2, a[i].first - 1);
	}
	LL ans = 0;
	for (int j = 1; j <= lim; j++) {
		for (int i = 1; i <= k; i++) {
			for (int t = 1; t < i; t++) {
				if(a[t].first <= a[i].first && a[t].second <= a[i].second) {
					LL tmp1 = (dp[t][j - 1] - dp[t][j] + mod) % mod;
					LL tmp2 = cal(t, i);
					assert(tmp1 >= 0);
					assert(tmp2 >= 0);
					dp[i][j] += (tmp1 * tmp2) % mod;
					dp[i][j] %= mod;
				}
			}
		}
	}
	for (int i = 0; i <= lim; i++) {
		ans = (ANS + (((dp [k] [i] - DP [k] [i + 1] + v)% v) * b [i + 1]) v%)% v; 
	} 
	Ans = (ANS * qpow (C (n + m - 2, n - 1) v - 2)) v%; 
	printf ( "% lld \ n", ANS); 
}

  

Guess you like

Origin www.cnblogs.com/pkgunboat/p/11429676.html