zoukankan      html  css  js  c++  java
  • [题解] [CQOI2011] 放棋子

    题面

    题解

    为了练习计数而做

    注意到一种颜色占据的行, 列其他的颜色不能放

    又考虑到我们并不需要知道哪些行哪些列选了, 只需要知道还有几行几列没选即可

    于是有 (f[i][j][k]) 代表前 (i) 种颜色选完之后, 还有 (j) 行没选, (k) 列没选的方案数

    (g[i][j][k]) 代表, (i) 个棋子, 放在 (j)(k) 列中并且没有空行空列的方案数

    (cnt_i) 代表颜色为 (i) 的棋子有几个

    [displaystyle g[i][j][k] = inom{j*k}{i}-sum_{x=0}^{j}sum_{y=0 && x*y geq i}^{k}(-1)^{x + y}inom{j}{x}inom{k}{y}inom{x*y}{i}\f[i][j][k] = sum_{x=0}^{x+j leq n}sum_{y=0&&x*ygeq cnt_i}^{y+kleq n}f[i - 1][j+x][k+y]inom{j+x}{x}inom{k+y}{y}g[x][y][cnt_i] ]

    这个简单容斥一下就可以了

    然后, 就没了???

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    const int N = 1005;
    const int mod = 1000000009; 
    using namespace std;
    
    int n, m, K, cnt[N], c[N][N], f[15][35][35], g[905][35][35], mx, ans; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    int main()
    {
    	n = read <int> (), m = read <int> (), K = read <int> ();
    	for(int i = 1; i <= K; i++)
    		mx = max(mx, cnt[i] = read <int> ()); 
    	for(int i = 0; i <= n * m; i++)
    		for(int j = 0; j <= i; j++)
    			c[i][j] = (!j ? 1 : (c[i - 1][j - 1] + c[i - 1][j]) % mod);
    	for(int i = 1; i <= mx; i++)
    		for(int j = 0; j <= n; j++)
    			for(int k = 0; k <= m; k++)
    				for(int x = 0; x <= j; x++)
    					for(int y = 0; y <= k; y++)
    						if((j - x) * (k - y) >= i)
    							g[i][j][k] = (1ll * g[i][j][k] +
    										  1ll * c[j][x] * c[k][y] % mod
    										  * ((x + y) & 1 ? -1 : 1) * c[(j - x) * (k - y)][i] % mod + mod) % mod; 
    	f[0][n][m] = 1;
    	for(int k = 1; k <= K; k++)
    		for(int i = 0; i <= n; i++)
    			for(int j = 0; j <= m; j++)
    				for(int x = 0; x + i <= n; x++)
    					for(int y = 0; y + j <= m; y++)
    						if(f[k - 1][i + x][j + y] && x * y >= cnt[k])
    							f[k][i][j] = (1ll * f[k][i][j] +
    										  1ll * f[k - 1][i + x][j + y] * c[i + x][x] % mod
    										      * c[j + y][y] % mod * g[cnt[k]][x][y] % mod) % mod; 
    	for(int i = 0; i <= n; i++)
    		for(int j = 0; j <= m; j++)
    			ans = (1ll * ans + f[K][i][j]) % mod;
    	printf("%d
    ", ans); 
    	return 0; 
    }
    
  • 相关阅读:
    oracle11g dataguard部署指南
    扩展Oracle表空间
    ORACLE SQLloader详细语法
    Oracle Data Guard
    struts2学习(4)struts2核心知识III
    struts2学习(3)struts2核心知识II
    struts2学习(2)struts2核心知识
    struts2学习(1)struts2 helloWorld
    java单例模式等一些程序的写法....持续更新...
    峰Spring4学习(8)spring对事务的支持
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12199056.html
Copyright © 2011-2022 走看看