luogu 2051 [AHOI2009]中国象棋
luogu 2051 [AHOI2009]中国象棋
真是一道令人愉♂悦丧心并框的好题。。。
首先“没有一个炮可以攻击到另一个炮”有个充分条件就是没有三个炮在同一行或同一列。证明:显然。
所以每行/每列最多2个炮。
还有一个点就是任意交换行和列不会改变这个方案的可行性。
那么可以脑补摆完前i行之后就把所有列排个序,会有摆了1个的列,摆了2个的列和没摆的列。
如果是桶排,就记录一下每个有多少就行了。
所以需要3个桶。可以省掉一个,因为知道了总共m列。
那么设f[i][j][k]为摆完了前i行,且j列摆了1个炮,k列摆了2个炮,你摆放的总方案数,然后滚动一下第一维
然后很多种情况,有注释。
PS.要多取膜!!!被坑到了
// It is made by XZZ
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Fname "cchess"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
#define mod 9999973
il int gi(){
    rg int x=0;rg bool flg=0;rg char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return flg?-x:x;
}
ll f[2][101][101];
il vd add(ll&a,ll b){a+=b;if(a>=mod)a-=mod;}
int main(){
#ifdef xzz
	freopen(Fname".in","r",stdin);
	freopen(Fname".out","w",stdout);
#endif
	int n=gi(),m=gi(),now=1;
	f[0][0][0]=1;
	rg ll t;
	rep(i,0,n-1){
		now^=1;
		memset(f[now^1],0,sizeof f[now^1]);
		drep(j,m,0)drep(k,m-j,0)if(f[now][j][k]){
			t=(f[now][j][k]%=mod);
			//第i行
			add(f[now^1][j][k],t);//不放
			add(f[now^1][j+1][k],t*(m-j-k)%mod);//放一个 新占一列
			if(j)add(f[now^1][j-1][k+1],t*j%mod);//放一个 与一列放了一个的放一起
			if(m-j-k>1)add(f[now^1][j+2][k],t*(m-j-k)*(m-j-k-1)/2%mod);//放两个 新占两列
			if(j&&m-j-k>0)add(f[now^1][j][k+1],t*(m-j-k)*j%mod);//放两个 一个新占一列 另一个与一列放了一个的放一起
			if(j>1)add(f[now^1][j-2][k+2],t*j*(j-1)/2%mod);//放两个 都与一列放了一个的放一起
		}
	}
	ll ans=0;
	now^=1;
	rep(i,0,m)rep(j,0,m-i)add(ans,f[now][i][j]);
	printf("%lld\n",ans);
	return 0;
}
luogu 2051 [AHOI2009]中国象棋的更多相关文章
- Luogu 2051[AHOI2009]中国象棋 - DP
		Description 在 $n * m$ 的格子上放若干个炮, 使得每个炮都不能攻击到其他炮 Solution 定义数组f[ i ][ j ][ k ] 表示到了第 i 行, 已经有2个炮的列数为 ... 
- [Luogu P2051] [AHOI2009]中国象棋 (状压DP->网格DP)
		题面 传送门:https://www.luogu.org/problemnew/show/P2051 Solution 看到这题,我们不妨先看一下数据范围 30pt:n,m<=6 显然搜索,直接 ... 
- Luogu P2051 [AHOI2009]中国象棋(dp)
		P2051 [AHOI2009]中国象棋 题面 题目描述 这次小可可想解决的难题和中国象棋有关,在一个 \(N\) 行 \(M\) 列的棋盘上,让你放若干个炮(可以是 \(0\) 个),使得没有一个炮 ... 
- luogu P2051 [AHOI2009]中国象棋
		统计方案,果断 dp 注意到合法方案即为每一行,每一列的棋子数不超过2 设\(f_{i,j,k}\)表示放到第\(i\)行,有\(j\)列可以放2个,有\(k\)列可以放1个的方案 然后就随便讨论一下 ... 
- 洛谷.2051.[AHOI2009]中国象棋(DP)
		题目链接 /* 每行每列不能超过2个棋子,求方案数 前面行对后面行的影响只有 放了0个.1个.2个 棋子的列数,与排列方式无关 所以设f[i][j][k]表示前i行,放了0个棋子的有j列,放了1个棋子 ... 
- BZOJ1801或洛谷2051 [AHOI2009]中国象棋
		BZOJ原题链接 洛谷原题链接 这题挺难想状态的,刚看题感觉是状压,但数据\(100\)显然不可能. 注意到每行每列只能放\(0\sim 2\)个棋子,所以我们可以将这个写入状态. 设\(f[i][j ... 
- Luogu P2051[AHOI2009]中国象棋【dp】By cellur925
		题目传送门 题目大意:给定一个$n*m$的棋盘,求放三个“炮”使它们不共行也不共列的方案数.($n,m$$<=100$) 这题主要是转移比较困难,因为情况比较多,所以需要冷静大胆细心地进行分情况 ... 
- 洛谷2051 [AHOI2009]中国象棋
		题目链接 题意概述:n行m列棋盘放若干个棋子每行每列最多两个求方案总数,答案对9999973取模. 可以比较容易看出这是个dp,设f[i][j][k]表示前i行j列放1个棋子k列放2个棋子的方案总数. ... 
- 洛谷  P2051 [AHOI2009]中国象棋 解题报告
		P2051 [AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法. ... 
随机推荐
- Math Summary 数论总结
			一.素数 Miller-Rabin 首先介绍一下伪素数:若n是一个正整数,且存在正整数a满足$a^{n-1}\equiv1\;(mod\;n)$ (费马小定理,但n不一定为素数) 那么我们说n是基于a ... 
- C/C++——new/delete和malloc/free的区别
			new/delete和malloc/free的区别 扩容操作: 对于malloc是有一个realloc函数对应用于扩容的: 对于new,只能再new一个,for循环赋值过去,把原来的delete掉: ... 
- 【Webpack】学习随笔
			参考链接:http://www.runoob.com/w3cnote/webpack-tutorial.html Webpack 是一个前端资源加载/打包工具. Webpack 可以将多种静态资源 j ... 
- virtualbox+vagrant学习-5-Boxes-1-简介
			Boxes boxes是vagrant环境的包格式.在vagrant支持的任何平台上,任何人都可以使用一个box来创建一个相同的工作环境.vagrant box实用程序提供了管理boxes的所有功能. ... 
- 利用maven开发springMVC项目(三)——数据库配置
			前两节介绍了开发环境的搭建以及框架的配置 现在主要介绍在eclipse中如何将SpringMVC.hibernate.mysql数据库结合起来. 数据库配置 下面,就要通过一个简单的例子,来介绍Spr ... 
- JNI由浅入深_5_基本类型应用
			1.基本类型应用 对于JNI处理基本类型还是比较简单的,下面是Java代码: <span style="font-size:14px;"> public native ... 
- HDU 1102(Constructing Roads)(最小生成树之prim算法)
			题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1102 Constructing Roads Time Limit: 2000/1000 MS (Ja ... 
- 【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C语言)
			#include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Positio ... 
- C++练习 | 递归判断二叉树是否同构
			#include <iostream> using namespace std; struct Tree { int data; Tree *lchild; Tree *rchild; } ... 
- js数组的处理使用
			var users = [ {name: "张含韵", "email": "zhang@email.com"}, {name: " ... 
