首页 > 其他分享 >[ABC265F] Manhattan Cafe 题解

[ABC265F] Manhattan Cafe 题解

时间:2023-12-24 14:12:18浏览次数:47  
标签:题解 sum sum2 Manhattan && 对角线 Cafe ll mod

[ABC265F] Manhattan Cafe 题解

思路解析

很有思维难度的一道题。思路是dp,\(f[i][j][k]\) 表示已经计算了 \(i\) 维,距离点 \(p\) 的距离为 \(j\) ,距离点 \(q\) 的距离为 \(k\) 时的整点 \(r\) 个数,由此可见我们的每一维都可以从上一维推出来,也即 \(f[i][j][k]\) 可以由 \(f[i-1][j-\Delta j][k-\Delta k]\) 推出,这里的 \(\Delta\) 是指对于每一个 \(r\) ,它和 \(p\) 和 \(q\) 在当前这一维上所需要增加的值,具体内容可以参考这张图:

由此图可见我们需要分类讨论在这一维上 \(r\) 和 \(p\) 和 \(q\) 之间的位置关系,其过程如下:

  • 这里的 \(s\) 代表的是 \(\left|p[i]-q[i]\right|\),也就是 \(p[i]\) 和 \(q[i]\) 之间的区间长度。

如果你能想到这一步,非常好,你已经获得了一个 \(O(nd^3)\) 的程序,代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const ll N = 110, D = 1010, mod = 998244353;
ll n, d;
ll p[N], q[N];
ll f[N][2 * D][D], sum[2 * D][D], sum2[2 * D][D];
int main() {
	cin >> n >> d;
	for(int i = 1; i <= n; i++) {
		cin >> p[i];
	}
	for(int i = 1; i <= n; i++) {
		cin >> q[i];
	}
	f[0][0][0] = 1;
	for(int i = 1; i <= n; i++) {
		ll s = abs(p[i] - q[i]);
		for(int j = 0; j <= 2 * d; j++) {
			for(int k = 0; k <= d; k++) {
				f[i][j][k] = 0;
				for(int l = 0; l <= s; l++) {
					if(j - l >= 0 && k - s + l >= 0) {
						f[i][j][k] += f[i - 1][j - l][k - s + l];
						f[i][j][k] %= mod;
					}
				}
				for(int l = 1; j - l >= 0 && k - s - l >= 0; l++) {
					if(j - l >= 0 && k - s - l >= 0) {
						f[i][j][k] += f[i - 1][j - l][k - s - l];
						f[i][j][k] %= mod;
					}
				}
				for(int l = 1; j - s - l >= 0 && k - l >= 0; l++) {
					if(j - s - l >= 0 && k - l >= 0) {
						f[i][j][k] += f[i - 1][j - s - l][k - l];
						f[i][j][k] %= mod;
					}
				}
			}
		}
	}
	ll ans = 0;
	for(ll j = 0; j <= d; j++) {
		for(ll k = 0; k <= d; k++) {
			if(abs(j - k) <= d) {
				ans += f[n][j][k];
				ans %= mod;
			}
		}
	}
	cout << ans;
	return 0;
}

但很遗憾此题数据为 \(n \leq 100, d \leq 1000\) 无法通过。可是我们发现每一次的 \(f[i][j][k]\) 的累加都是成对角线形状累加的,于是便可想到使用前缀和进行优化:

  • 对于第一种情况:可见这种情况的对角线是一条垂直于主对角线的对角线,可以用一个 \(sum[j][k]\) 表示 \(j, k\) 所存在的这条对角线从 \(f[i-1][0][k+1]\) 一直累加到 \(f[i-1][j][k]\) 的值。但是需要注意我们只选取对角线中结尾为 \(j, k\) 且长度最长为 \(s\) ,因为只有这些情况的取值是符合这种情况分类讨论的判断条件的。以及如果对角线的两端小于 \(0\) ,也就是两端不存在,我们就特判两端是否存在,只统计剩余的存在的部分(我就是因为这里卡了一晚上。

  • 对于第二和第三种情况:可见它们所经过的对角线是一条平行于主对角线的对角线,可以用一个 \(sum2[j][k]\) 表示从这条对角线的开头累加到 \(f[i-1][j][k]\) 的值。

具体内容见下图:

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const ll N = 110, D = 1010, mod = 998244353;
ll n, d;
ll p[N], q[N];
ll f[N][2 * D][D], sum[2 * D][2 * D], sum2[2 * D][2 * D];
int main() {
	cin >> n >> d;
	for(ll i = 1; i <= n; i++) {
		cin >> p[i];
	}
	for(ll i = 1; i <= n; i++) {
		cin >> q[i];
	}
	f[0][0][0] = 1;
	for(int i = 1; i <= n; i++) {
		memset(sum, 0, sizeof(sum));	//别忘了清空数组
		memset(sum2, 0, sizeof(sum2));
		for(ll j = 0; j <= d; j++) {
			for(ll k = 0; k <= d; k++) {
				if(j - 1 >= 0) {
					sum[j][k] += sum[j - 1][k + 1];
					sum[j][k] %= mod;	//记得取模
				}
				sum[j][k] += f[i - 1][j][k];
				sum[j][k] %= mod;
				if(j - 1 >= 0 && k - 1 >= 0) {
					sum2[j][k] += sum2[j - 1][k - 1];
					sum2[j][k] %= mod;
				}
				sum2[j][k] += f[i - 1][j][k];
				sum2[k][k] %= mod;
			}
		}
		ll s = abs(p[i] - q[i]);
		for(ll j = 0; j <= d; j++) {
			for(ll k = 0; k <= d; k++) {
				f[i][j][k] = 0;
				if(k - s >= 0) {	//细节特判
					if(j - s >= 0) {
						f[i][j][k] += (sum[j][k - s] - sum[j - s][k] + f[i - 1][j - s][k]) % mod;
					}
					else {
						f[i][j][k] += (sum[j][k - s] - sum[0][k - s + j] + f[i - 1][0][k - s + j]) % mod;
					}
				}
				else {
					if(j - s >= 0) {
						f[i][j][k] += (sum[j - s + k][0] - sum[j - s][k] + f[i - 1][j - s][k]) % mod;
					}
					else {
						f[i][j][k] += (sum[j - s + k][0] - sum[0][k - s + j] + f[i - 1][0][k - s + j]) % mod;
					}
				}
				f[i][j][k] %= mod;
				if(j - 1 >= 0 && k - s - 1 >= 0) {
					f[i][j][k] += sum2[j - 1][k - s - 1];
					f[i][j][k] %= mod;
				}
				if(j - s - 1 >= 0 && k - 1 >= 0) {
					f[i][j][k] += sum2[j - s - 1][k - 1];
					f[i][j][k] %= mod;
				}
			}
		}
	}
	ll ans = 0;
	for(ll j = 0; j <= d; j++) {
		for(ll k = 0; k <= d; k++) {
			ans += f[n][j][k];
			ans %= mod;
		}
	}
	cout << ans;
	return 0;
}

标签:题解,sum,sum2,Manhattan,&&,对角线,Cafe,ll,mod
From: https://www.cnblogs.com/2020luke/p/17924329.html

相关文章

  • ABC334 全套题解
    A-ChristmasPresent简单题。voidslv(){ inta=Read<int>(),b=Read<int>(); if(a>b)Puts("Bat"); elsePuts("Glove"); return;}B-ChristmasTrees也是简单题。constexpri128INF=-1e18;i128a,m,l,r;voidslv(......
  • 题解 ABC334G【Christmas Color Grid 2】
    先求出初始时绿连通块数量。将一个绿色格子染成红色,会改变绿连通块数量,当且仅当这个绿色格子是孤点或割点。如果是孤点,会使得绿连通块数量减少一;如果是割点,会使得绿连通块数量增加它所在的点双数量减一。根据上述规则可以求出每个绿色格子染红后的绿连通块数量,求平均值即可。时......
  • 题解 ABC334F【Christmas Present 2】
    设\(f_i\)表示假设只有编号为\(1\simi\)的点,此时的答案。\(f_n\)即为所求。显然有:\[f_i=\min\limits_{i-k\lej<i}\{f_j+dis(s\toj+1\toj+2\to\cdots\toi)\}+dis(i\tos)\]当\(i\toi+1\)时,大括号内部全局增加\(dis(i\toi+1)\),可以全局打标记后单调队列维护。......
  • 题解 ABC334E【Christmas Color Grid 1】
    先求出初始时绿连通块数量。枚举每个红色格子,将其染成绿色本应增加一个绿连通块,但是它每与一个绿连通块相邻,就又会减少一个绿连通块。根据上述规则可以求出每个红色格子染绿后的绿连通块数量,求平均值即可。时间复杂度\(O(nm)\)。//Problem:E-ChristmasColorGrid1//Co......
  • 检查Windows更新问题解决
    在任务栏搜索框输入cmd,点击右侧的“以管理员身份运行”,打开后输入:(建议复制粘贴,防止输入有误出现错误提示等请忽略*)SCconfigwuauservstart=auto回车(Enter按键)SCconfigbitsstart=auto回车(Enter按键)SCconfigcryptsvcstart=auto回车(Enter按键)SCconfigtrustedin......
  • 【题解】洛谷P1068 [NOIP2009 普及组] 分数线划定 (map)
    ##题目描述世博会志愿者的选拔工作正在A市如火如荼的进行。为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的$150\%$划定,即如果计划录取$m$名志愿者,则面试分数线为排名第$m\times150\%$(向......
  • P3893 [GDOI2014] Beyond 题解
    P3893[GDOI2014]Beyond题解思路称第一个字符串为\(A\),第二个字符串\(B\)。考虑枚举环长\(L\),那么如果\(L\)是可行的,当且仅当存在一个位置\(i\),使得\(A_{1\simi}=B_{L-i+1,L},A_{i+1\simL}=B_{1,L-i}\),也就是\(A_{1\simL}\)的一个前缀和\(B_{1\s......
  • 【洛谷 P1781】宇宙总统 题解(高精度+结构体排序)
    宇宙总统题目描述地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。输入格式第一行为一个整数,代表竞选总统的人数。接下来有行,分别为第一个候选人到第个候选人的票数。输出格式共两行,第一行是......
  • 题解:【XR-3】核心城市
    题解:【XR-3】核心城市思路一:考虑由特例推广到一般1、很容易想到先考虑一个关键点的情况,然后再推广到一般情况。2、一个点肯定选距离上最平衡的那个点,即树的中心。接着在中心周围贪心的选剩下的(k-1)个关键点即可。3、这里有一个误区:各点到某点的距离最小,是找树的中心而不是重......
  • 闭合区域面积统计 题解
    题目描述计算一个\(10\times10\)矩阵中由\(1\)围成的图形的面积。如下所示,在\(10\times10\)的二维数组中,\(1\)围住了\(15\)个点,因此面积为\(15\)。000000000000001110000000100100000001001000100010100101......