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;
}
相关推荐
码客-ygluu7 分钟前
一个通用游戏数据服务器
c++·架构
another heaven13 分钟前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
Code_Solitude16 分钟前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司23 分钟前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
YLCHUP3 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
xiaoye-duck3 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
思麟呀3 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落4 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
旖旎夜光5 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习
ShineWinsu5 小时前
对于Qt:QTabWidget常见属性的解析
开发语言·数据库·c++·qt·浏览器·qtabwidget·标签页