2026-10-03 hetao1733837 的刷题记录

AT_arc157_c ARC157C YY Square

原题链接:ARC157C YY Square

分析

感觉昨天晚上睡觉之前想的也不是很对啊......就是,我们只需要统计有多少条路径上有 i i i 个 Y,以及 Y 的段数就行了。但是,这个复杂度......我不敢恭维啊......所以,还是没有切。

所以,还是要记录具体到了什么位置。


那么,我们分两次计算,由于 ( a + b ) 2 = a 2 + 2 a b + b 2 (a+b)^2=a^2+2ab+b^2 (a+b)2=a2+2ab+b2,所以,我们分两次计算 a 2 a^2 a2 和 2 a b 2ab 2ab。

所以,我们设 d p i , j , k dp_{i,j,k} dpi,j,k 表示在位于 ( x , y ) (x,y) (x,y) 时,我们要求的是 k k k 次方的方案数。

转移有:

  • c i , j = c_{i,j}= ci,j=X, d p i , j , 1 = d p i − 1 , j , 1 + d p i , j − 1 , 1 , d p i , j , 2 = d p i − 1 , j , 2 + d p i , j − 1 , 2 dp_{i,j,1}=dp_{i-1,j,1}+dp_{i,j-1,1},dp_{i,j,2}=dp_{i-1,j,2}+dp_{i,j-1,2} dpi,j,1=dpi−1,j,1+dpi,j−1,1,dpi,j,2=dpi−1,j,2+dpi,j−1,2
  • c i , j = c_{i,j}= ci,j=Y, d p i , j , 2 = d p i − 1 , j , 1 + c i − 1 , j = Y × C i + j − 3 i − 2 + d p i , j − 1 , 1 + c i , j − 1 = Y × C i + j − 3 i − 1 , d p i , j , 2 = d p i − 1 , j , 1 + c i − 1 , j = Y × ( C i + j − 3 i − 2 + 2 × d p i − 1 , j , 1 ) + d p i , j − 1 , 1 + c i , j − 1 = Y × ( C i + j − 3 i − 1 + 2 × d p i , j − 1 , 1 ) dp_{i,j,2}=dp_{i-1,j,1}+c_{i-1,j}=Y\times C_{i+j-3}^{i-2}+dp_{i,j-1,1}+c_{i,j-1}=Y\times C_{i+j-3}^{i-1},dp_{i,j,2}=dp_{i-1,j,1}+c_{i-1,j}=Y\times (C_{i+j-3}^{i-2}+2\times dp_{i-1,j,1})+dp_{i,j-1,1}+c_{i,j-1}=Y\times (C_{i+j-3}^{i-1}+2\times dp_{i,j-1,1}) dpi,j,2=dpi−1,j,1+ci−1,j=Y×Ci+j−3i−2+dpi,j−1,1+ci,j−1=Y×Ci+j−3i−1,dpi,j,2=dpi−1,j,1+ci−1,j=Y×(Ci+j−3i−2+2×dpi−1,j,1)+dpi,j−1,1+ci,j−1=Y×(Ci+j−3i−1+2×dpi,j−1,1)

那个组合数是走到 ( i − 1 , j ) (i-1,j) (i−1,j) 的方案数和走到 ( i , j − 1 ) (i,j-1) (i,j−1) 的方案数。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
const int N = 2005;
int h, w;
int fac[N << 1], inv[N << 1];
string s;
char c[N][N];
int dp[N][N][5];
int qpow(int a, int b){
	int res = 1;
	while (b){
		if (b & 1)
			res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}
int C(int n, int m){
	if (n < 0 || m < 0 || n < m)
		return 0;
	return fac[n] * inv[n - m] % mod * inv[m] % mod;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> h >> w;
	fac[0] = 1;
	for (int i = 1; i < (N << 1); i++){
		fac[i] = fac[i - 1] * i % mod; 
	}
	inv[(N << 1) - 1] = qpow(fac[(N << 1) - 1], mod - 2);
	for (int i = (N << 1) - 2; i >= 0; i--){
		inv[i] = inv[i + 1] * (i + 1) % mod;
	}
	for (int i = 1; i <= h; i++){
		cin >> s;
		for (int j = 1; j <= w; j++){
			c[i][j] = s[j - 1];
		}
	}
	for (int i = 1; i <= h; i++){
        for (int j = 1; j <= w; j++){
            if (c[i][j] == 'X'){
                dp[i][j][1] = (dp[i - 1][j][1] + dp[i][j - 1][1]) % mod;
                dp[i][j][2] = (dp[i - 1][j][2] + dp[i][j - 1][2]) % mod;
            } 
            else{
                dp[i][j][1] = (dp[i - 1][j][1] + (c[i - 1][j] == 'Y') * C(i + j - 3, i - 2) + dp[i][j - 1][1] + (c[i][j - 1] == 'Y') * C(i + j - 3, i - 1)) % mod;
                dp[i][j][2] = (dp[i - 1][j][2] + (c[i - 1][j] == 'Y') * (C(i + j - 3, i - 2) + 2 * dp[i - 1][j][1]) % mod + dp[i][j - 1][2] + (c[i][j - 1] == 'Y') * (C(i + j - 3, i - 1) + 2 * dp[i][j - 1][1]) % mod) % mod;
            }
        }
    }
	cout << dp[h][w][2];
}

AT_arc157_d ARC157D YY Garden

原题链接:ARC157D YY Garden

分析

这么暴力???

就是说,我们假设竖着切了 p p p 条线,横着切了 q q q 条线,然后,我们必须要求每一行 Y 的数量都是 2 p 2p 2p 的倍数,每一列 Y 的数量都是 2 q 2q 2q 的倍数。然后,拿前缀和直接统计一下就做完了......这个 check 的次数不会很多......

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
const int N = 2005;
int h, w;
char c[N][N];
int sh[N], sw[N];
int sum[N][N];
int p[N], q[N];
int cnth[N], cntw[N];
int tot;
int ans;
void check(int kh){
	int kw = tot * 2 / kh;
	int ch = 0, cw = 0;
	for (int i = 1; i <= h; i++){
		if (sh[i] != sh[i - 1] && sh[i] % kh == 0){
			p[++ch] = i;
		}
	}
	for (int j = 1; j <= w; j++){
		if (sw[j] != sw[j - 1] && sw[j] % kw == 0){
			q[++cw] = j;
		}
	}
	if (ch * 2 != kw || cw * 2 != kh)
		return ;
	for (int i = 1; i <= ch; i++){
		for (int j = 1; j <= cw; j++){
			int tmp = sum[p[i]][q[j]] - sum[p[i - 1]][q[j]] - sum[p[i]][q[j - 1]] + sum[p[i - 1]][q[j - 1]];
			if (tmp != 2)
				return ;
		}
	}
	memset(cnth, 0, sizeof(cnth));
	memset(cntw, 0, sizeof(cntw));
	for (int i = 1; i <= h; i++){
		if (sh[i] % kh == 0){
			cnth[sh[i] / kh]++;
		}
	}
	for (int j = 1; j <= w; j++){
		if (sw[j] % kw == 0){
			cntw[sw[j] / kw]++;
		}
	}
	int res = 1;
	for (int i = 1; i < ch; i++){
		res = res * cnth[i] % mod;
	}
	for (int j = 1; j < cw; j++){
		res = res * cntw[j] % mod;
	}
	ans = (ans + res) % mod;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> h >> w;
	string s;
	for (int i = 1; i <= h; i++){
		cin >> s;
		for (int j = 1; j <= w; j++){
			c[i][j] = s[j - 1];
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
			if (c[i][j] == 'Y'){
				sh[i]++;
				sw[j]++;
				sum[i][j]++;
			}
		}
	}
	for (int i = 1; i <= h; i++){
		sh[i] += sh[i - 1];
	}
	for (int j = 1; j <= w; j++){
		sw[j] += sw[j - 1];
	}
	tot = sh[h];
	if (tot % 2 == 1){
		cout << 0;
		return 0;
	}
	for (int i = 2; i <= h * w; i += 2){
		if (tot % i == 0){
			check(i);
		}
	}
	cout << ans;
}
相关推荐
kaixin_learn_qt_ing1 小时前
Qt&C++软件开发工程师
c++
UIU1141 小时前
-7 / 2 在 C 里是 -3,在 Python 里是 -4,谁算错了?
c++·学习·c#
BenedictHook1 小时前
技能商店 SkillHub:Windows端 AI Skill 管理工具,支持搜索、查看与安装
c++·agent·桌面应用·skill·windows开发·skillhub
无名猿1 小时前
指针算术与数组退化:数组名到底是不是指针
c++·内存管理·标准库·语法基础
汉克老师1 小时前
GESP2026年9月认证C++七级( 第一部分选择题(1~7题)精讲
c++·gesp·小学生·学c++编程
这张生成的图像能检测吗1 小时前
(论文速读)Object-Driven Multi-Layer Scene Decomposition:从单张图像恢复遮挡后的多层场景
人工智能·算法·计算机视觉·rgb-d·场景分解
嘎嘎风1 小时前
MiniMind 学习笔记之 01 一个 64M 的模型,凭什么像 ChatGPT?
算法
Evand J1 小时前
【MATLAB例程】三维快速扩展随机树(RRT)路径规划与到达角(AOA)定位算法|三维避障+定位仿真。附下载链接
开发语言·算法·matlab·路径规划·定位
程序员老陆1 小时前
C++ 悬空指针:从原理到工程级解决方案
开发语言·c++·程序设计