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;
    }
    
  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/mcggvc/p/13871766.html
Copyright © 2011-2022 走看看