zoukankan      html  css  js  c++  java
  • CF559C Gerald and Giant Chess(计数DP)

    CF559C Gerald and Giant Chess
    因为h,w范围很大,考虑求不合法方案数,最后用总方案数减去不合法的。
    (f(i)) 为从 ((1, 1)) 到第 i 个黑方格且不经过其他黑方格的方案数。
    可以得到状态转移方程:(第 i 个黑方格坐标为((i.x, i.y))。)

    [egin{aligned} f(i) = C_{i.x + i.y - 2}^{i.x - 1} - sum_{j.x leq i.x, j.y leq i.y} C_{i.x + i.y - j.x - j.y}^{i.x - j.x} cdot f(j) end{aligned} ]

    最终答案为:

    [egin{aligned} ans = C_{h + w - 2}^{h - 1} - sum_{j = 1}^{n} C_{h + w - j.x - j.y}^{h - j.x} cdot f(j) end{aligned} ]

    将输入的黑方格按x坐标为第一关键字,y坐标为第二关键字由小到大排序,组合数用乘法逆元直接算。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long lld;
    const int N = 2005;
    const int M = 1e5 + 5;
    const lld p = 1e9 + 7;
    lld fac[M << 1], inv[M << 1], f[N];
    int n, h, w;
    struct node {
    	int x, y;
    } a[N];
    bool cmp(node a, node b) {
    	if(a.x == b.x) return a.y < b.y;
    	return a.x < b.x;
    }
    lld powe(lld a, lld b) {
    	lld base = 1;
    	while(b) {
    		if(b & 1) base = (base * a) % p;
    		a = (a * a) % p; b >>= 1;
    	}
    	return base;
    }
    lld comb(lld x, lld y) {
    	if(x <= 0) return 0;
    	lld tmp = (fac[x] * inv[y]) % p;
    	tmp = (tmp * inv[x - y]) % p;
    	return tmp;
    }
    int main() {
    //	freopen("data.in", "r", stdin);
    	scanf("%d%d%d", &h, &w, &n);
    	for(int i = 1, x, y; i <= n; i++) {
    		scanf("%d%d", &a[i].x, &a[i].y);
    	}
    	fac[0] = inv[0] = 1;
    	for(int i = 1; i <= h + w; i++) {
    		fac[i] = (fac[i - 1] * lld(i)) % p;
    		inv[i] = powe(fac[i], p - 2);
    	}
    	sort(a + 1, a + 1 + n, cmp);
    	for(int i = 1; i <= n; i++) {
    		f[i] = comb(a[i].x + a[i].y - 2, a[i].x - 1);
    		for(int j = 1; j < i; j++) {
    			if(a[j].x <= a[i].x && a[j].y <= a[i].y) {
    				f[i] = f[i] - (comb(a[i].x + a[i].y - a[j].x - a[j].y, a[i].x - a[j].x) * f[j]) % p;
    				f[i] = (f[i] + p) % p;
    			}
    		}
    	}
    	lld ans = comb(h + w - 2, h - 1);
    	for(int i = 1; i <= n; i++) {
    		ans = ans - (comb(h + w - a[i].x - a[i].y, h - a[i].x) * f[i]) % p;
    		ans = (ans + p) % p;
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    8常用控件
    7对话框
    6控件
    5Lambda表达式
    4自定义信号和槽函数
    3信号与槽
    2指定父对象
    springboot整合activemq
    springboot整合springtask
    jvm与tomcat启动优化配置
  • 原文地址:https://www.cnblogs.com/mcggvc/p/13871766.html
Copyright © 2011-2022 走看看