这道题告诉我们推式子的时候头要够铁。

题意

问一个\(n\times m\)的棋盘,摆上\(n\times 2\)个中国象棋的炮使其两两不能攻击的方案数,对\(998244353\)取模。

\((n\leq m\leq 2000)或(n\leq m\leq 100000且m-n\leq 10)\)。

题解

怎么两个数据范围搞搞。

显然合法方案等价于每行每列炮的数量不超过\(2\),那么每一行就必定放\(2\)个炮了。

我们记\(f(n,m)\)为答案,考虑如何归约到规模更小的问题。

那么我们枚举最后一行炮的个数,分三类情况:

\(1\)、个数为\(0\),归约到\(f(n,m-1)\)。

\(2\)、个数为\(2\)(个数为\(1\)比较麻烦后面再说),那么先枚举放在这一列的是哪两行(\(\times \frac{n(n-1)}{2}\)),接着分类讨论这两行的另一个是否相同:

如果相同,则枚举这是哪一个\((\times (m-1))\),归约到\(f(n-2,m-2)\)。

如果不同,则这两行可以合并(同一行的唯一要求就是两个列不同),只要根据有序性\(\times 2\)即可,于是归约到\(f(n-1,m-1)\)。

\(3\)、个数为\(1\),那么先枚举占了最后一列的是哪一行\((\times n)\),再枚举这一行的另一个在哪一列\((\times (m-1))\),问题就转化为\(n-1\)行\(m-1\)列,其中有一列炮的个数\(\leq 1\)的方案数。

那么考虑容斥,用总方案数减去这一列放了两个的方案数。前者就是\(f(n-1,m-1)\),对于后者,进行与情况\(2\)相似的讨论,也可以进行计算。

可以发现\(n>m\)时\(f(n,m)=0\),于是复杂度就是\(O((m-n)n)\)。

代码里为了方便我将\(m\)减去了\(n\)。

#include<cstdio>
#include<cstring>
const int mod=998244353,inv2=(mod+1)/2;
inline int add(int a,int b)
{
return (a+=b)>=mod?a-mod:a;
}
inline int sub(int a,int b)
{
return (a-=b)<0?a+mod:a;
}
inline int mul(int a,int b)
{
return (long long)a*b%mod;
}
inline int qpow(int a,int b)
{
int res=1;
for(;b;a=mul(a,a),b>>=1)
if(b&1)
res=mul(res,a);
return res;
}
int n,m;
namespace solver1
{
const int N=2005;
int memo[N][N];
inline void init()
{
memset(memo,-1,sizeof(memo));
memo[1][0]=0;
memo[2][0]=1;
memo[3][0]=6;
return;
}
int f(int n,int m)
{
if(m<0)
return 0;
if(n==0)
return 1;
if(~memo[n][m])
return memo[n][m];
int res=0;
//0
res=add(res,f(n,m-1));
//1
res=add(res,mul(mul(n,n+m-1),f(n-1,m)));
if(n>=3)
res=sub(res,mul(mul(n,n+m-1),mul(mul(mul(n-1,n-2),inv2),add(mul(n+m-2,f(n-3,m)),mul(2,f(n-2,m))))));
//2
if(n>=2)
res=add(res,mul(mul(mul(n,n-1),inv2),add(mul(n+m-1,f(n-2,m)),mul(2,f(n-1,m)))));
return memo[n][m]=res;
}
inline void main()
{
init();
printf("%d\n",f(n,m-n));
return;
}
}
namespace solver2
{
const int N=1e5+5;
int memo[N][15];
inline void init()
{
memset(memo,-1,sizeof(memo));
memo[1][0]=0;
memo[2][0]=1;
memo[3][0]=6;
return;
}
int f(int n,int m)
{
if(m<0)
return 0;
if(n==0)
return 1;
if(~memo[n][m])
return memo[n][m];
int res=0;
//0
res=add(res,f(n,m-1));
//1
res=add(res,mul(mul(n,n+m-1),f(n-1,m)));
if(n>=3)
res=sub(res,mul(mul(n,n+m-1),mul(mul(mul(n-1,n-2),inv2),add(mul(n+m-2,f(n-3,m)),mul(2,f(n-2,m))))));
//2
if(n>=2)
res=add(res,mul(mul(mul(n,n-1),inv2),add(mul(n+m-1,f(n-2,m)),mul(2,f(n-1,m)))));
return memo[n][m]=res;
}
inline void main()
{
init();
printf("%d\n",f(n,m-n));
return;
}
}
signed main()
{
scanf("%d%d",&n,&m);
if(n<=2000&&m<=2000)
solver1::main();
else
solver2::main();
return 0;
}

洛谷P4831 Scarlet loves WenHuaKe的更多相关文章

  1. 洛谷 P1580 yyy loves Easter_Egg I

    洛谷 P1580 yyy loves Easter_Egg I 题解: 队列+字符串 #include <cstdio> #include <string> #include ...

  2. [洛谷2397]yyy loves Maths VI

    题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居然也不会,所以只好找你 题目描述 他让redbag找众数他还特意 ...

  3. 洛谷P3602 Koishi Loves Segments(贪心,multiset)

    洛谷题目传送门 贪心小水题. 把线段按左端点从小到大排序,限制点也是从小到大排序,然后一起扫一遍. 对于每一个限制点实时维护覆盖它的所有线段,如果超过限制,则贪心地把右端点最大的线段永远删去,不计入答 ...

  4. [CF327E]Axis Walking([洛谷P2396]yyy loves Maths VII)

    题目大意:给一个长度为$n(1\leqslant n\leqslant24)$的序列$S$和$k(0\leqslant k\leqslant2)$个数. 求有多少种$S$的排列方式使得其任何一个前缀和 ...

  5. [洛谷1580]yyy loves Easter_Egg I

    题目背景 Soha的出题效率着实让人大吃一惊.OI,数学,化学的题目都出好了,物理的题还没有一道.于是,Huntfire,absi2011,lanlan对soha进行轮番炸,准备炸到soha出来,不料 ...

  6. 洛谷P2397 yyy loves Maths VI (mode)

    P2397 yyy loves Maths VI (mode) 题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居 ...

  7. 洛谷P2396 yyy loves Maths VII

    P2396 yyy loves Maths VII 题目背景 yyy对某些数字有着情有独钟的喜爱,他叫他们为幸运数字;然而他作死太多,所以把自己讨厌的数字成为"厄运数字" 题目描述 ...

  8. 洛谷——P2393 yyy loves Maths II

    P2393 yyy loves Maths II 题目背景 上次蒟蒻redbag可把yyy气坏了,yyy说他只是小学生,蒟蒻redbag这次不坑他了. 题目描述 redbag给了yyy很多个数,要yy ...

  9. 洛谷 P4882 lty loves 96! 解题报告

    P4882 lty loves 96! 题目背景 众所周知,\(lty\)非常喜欢\(96\)这两个数字(想歪的现在马上面壁去),更甚于复读(人本复)! 题目描述 由于爱屋及乌,因此,\(lty\)对 ...

随机推荐

  1. 如何一步一步建立CAN通讯

    如何一步一步建立CAN通讯 2016-04-12 20:38:14来源: eefocus 关键字:CAN通讯  硬件环境   收藏 评论(0) 分享到 微博 QQ 微信 LinkedIn CAN通讯的 ...

  2. ccf201703-2学生排队

    问题描述 体育老师小明要将自己班上的学生按顺序排队.他首先让学生按学号从小到大的顺序排成一排,学号小的排在前面,然后进行多次调整.一次调整小明可能让一位同学出队,向前或者向后移动一段距离后再插入队列. ...

  3. iOS Swift WisdomScanKit图片浏览器功能SDK

    iOS Swift WisdomScanKit图片浏览器功能SDK使用 一:简介      WisdomScanKit 由 Swift4.2版编写,完全兼容OC项目调用. WisdomScanKit的 ...

  4. [agc011C]Squared Graph-[二分图]

    Description 传送门 Solution 我们以下考虑的情况都是原图中非孤立的点. 题目要求新图的连通块个数.这个不好算,我们考虑计算新图的联通块内的特征点(x,y),即无法通过移动找到(t, ...

  5. 探索sklearn | K均值聚类

    1 K均值聚类 K均值聚类是一种非监督机器学习算法,只需要输入样本的特征 ,而无需标记. K均值聚类首先需要随机初始化K个聚类中心,然后遍历每一个样本,将样本归类到最近的一个聚类中,一个聚类中样本特征 ...

  6. mfc CString,string,char* 之间的转换

    知识点: CString转char*,string string转char*,CString char* 转CString,string 一.CString转char*,string //字串转换测试 ...

  7. Qt FFMPEG+OpenCV开启摄像头

    //ffmpegDecode.h #ifndef __FFMPEG_DECODE_H__ #define __FFMPEG_DECODE_H__ #include "global.h&quo ...

  8. cocos2d-x学习记录6——自定义Button

    cocos2d-x中封装CCMenuItem等相关按钮,但是有些时候需要自己封装按钮,这样能够更加灵活的实现对应功能. 自定义Button,需要重写OnEnter()和onExit()函数,并在对应函 ...

  9. [LOJ#6039].「雅礼集训 2017 Day5」珠宝[决策单调性]

    题意 题目链接 分析 注意到本题的 \(C\) 很小,考虑定义一个和 \(C\) 有关的状态. 记 \(f(x,j)\) 表示考虑到了价格为 \(x\) 的物品,一共花费了 \(j\) 元的最大收益. ...

  10. LeetCode Search for a Range (二分查找)

    题意 Given a sorted array of integers, find the starting and ending position of a given target value. ...