码迷,mamicode.com
首页 > 其他好文 > 详细

ARC 118 E - Avoid Permutations

时间:2021-05-24 15:41:47      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:include   bit   amp   c++   ace   else   实现   pac   clu   

  • 求出所有可能棋盘的不经过任意障碍的方案数之和。

  • 考虑容斥,对于一条钦定经过 \(k\) 个障碍的路线,对答案的贡献为 \({-1}^k\) 乘以可以对应的棋盘数。

    可以发现棋盘数只与路线中钦定的障碍并且该障碍并未明确的个数有关。

    并且实际运算中每次遇到障碍转移时乘以 \(-1\) 即可。

  • 于是将未明确的障碍个数,当前行列是否钦定障碍,加入状态,记为 \(f_{x,y,i,0/1,0/1}\)

    转移考虑选不选即可。

  • 实现推荐处理出每个格子是否能被钦定,并用刷表法进行递推。

#include <bits/stdc++.h>
using namespace std;

const int N = 205, mod = 998244353; 

int n, p[N][N], f[N][N][N][2][2], fac[N], m;

void sub_(int &x, int y) {
	x = x - y < 0 ? x - y + mod : x - y;
}

void add_(int &x, int y) {
	x = x + y >= mod ? x + y - mod : x + y;
}

int main() {
	scanf("%d", &n), fac[0] = 1;
	
	for (int i = 0; i <= n + 1; i++)
		p[i][n + 1] = p[n + 1][i] = p[0][i] = p[i][0] = -1;
	
	for (int i = 1, x; i <= n; i++) {
		scanf("%d", &x), fac[i] = 1ll*fac[i - 1]*i%mod; 
		
		if (x == -1)
			m++;
		else {
			for (int j = 1; j <= n; j++)
				p[j][x] = -1;
			
			for (int j = 1; j <= n; j++)
				p[i][j] = -1;
			
			p[i][x] = 1;
		}
	}
	
	f[0][0][0][0][0] = 1;
	
	for (int i = 0; i <= n + 1; i++)	
		for (int j = 0; j <= n + 1; j++)
			for (int k = 0; k <= n; k++)
				for (int r = 0; r < 2; r++)
					for (int c = 0, now; c < 2; c++)
						if ((now = f[i][j][k][r][c])) {
							add_(f[i + 1][j][k][0][c], now);
							add_(f[i][j + 1][k][r][0], now);
							
							if (!r && ~p[i][j + 1])
								sub_(f[i][j + 1][k + (!p[i][j + 1])][1][1], now);
							
							if (!c && ~p[i + 1][j])
								sub_(f[i + 1][j][k + (!p[i + 1][j])][1][1], now);							
						}
	
	int ans = 0;
	
	for (int i = 0; i <= m; i++)
		ans = (ans + 1ll*f[n + 1][n + 1][i][0][0]*fac[m - i])%mod;
	
	printf("%d\n", ans);
} 

ARC 118 E - Avoid Permutations

标签:include   bit   amp   c++   ace   else   实现   pac   clu   

原文地址:https://www.cnblogs.com/iqx37f/p/14782899.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!