ABC-269解题报告

比赛传送门

D. Do use hexagon grid

题目传送门

\(n^2\) 枚举两个格点,判断是否能直接走,能则连边,最后用 dfs 计算连通块个数。

E. Last Rook

题目传送门

由于不需要考虑斜向的冲突,所以考虑行和列分开二分。以行为例:

如果有若干连续行的棋子数量小于行数,则答案一定在这些行中,以此作为二分的 check。

F. Numbered Checker

题目传送门

显然每一行剩下的数都是一个等差数列。

考虑奇偶行分开计算:对于奇数行,只有奇数列能产生贡献;对于偶数行,只有偶数列能产生贡献。以奇数行为例:

具体地,若输入的四界分别为 \(u,d,l,r\),则只考虑奇数行时,我们将四界缩紧为 \(u',d',l',r'\)(为方便接下来处理),此时能产生贡献的列数为 \(len_{row}=(r'-l')/2+1\),行数为 \(len_{column}=(d'-u')/2+1\)

显然贡献的左上角的值为 \(s_1=(u'-1)\times m+l'\),右上角为 \(s_2=(u'-1)\times m+r'\),则第一行的和 \(sum_{u'}=(s_1+s_2)\times len_{row}\)

第二个产生贡献的行(即 \(u'+2\) 行)的和为 \(sum_{u'+2}=sum_{u'}+len_{row}\times 2m\),第三行为 \(sum_{u'+4}=sum_{u'}+len_{row}\times 4m\) 以此类推。可以发现每一行都含有一个 \(sum_{u'}\) 的项,单独提出来,得到 \(sum_{u'}\times len_{column}\),而每一行新加的贡献为 \(len_{row}\times 0m+len_{row}\times 2m+len_{row}\times 4m\cdots\),这也可以很容易得用等差数列求得。

偶数行偶数列的情况同理,由于操作完全相同,可以封装成函数调用两遍。

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int add(int a,int b) {return (a+b)%mod;}
int mul(int a,int b) {return a*b%mod;}
signed main() {
	int inv2=(mod+1)/2;
	int n,m,q;
	cin>>n>>m>>q;
	while(q--) {
		int l,r,u,d,ans=0;
		cin>>u>>d>>l>>r;
		auto solve=[&](bool flag) {
			int u1=u,d1=d,l1=l,r1=r;
			if(u1%2==flag) u1++;
			if(d1%2==flag) d1--;
			if(l1%2==flag) l1++;
			if(r1%2==flag) r1--;
			int lenrow=(r1-l1)/2+1,lencol=(d1-u1)/2+1;
			int res=mul(mul(add(add(mul(u1-1,m),l1),add(mul(u1-1,m),r1)),lenrow),inv2);
			(ans+=mul(res,lencol))%=mod;
			(ans+=mul(mul(mul(mul(2*(lencol-1),m),lencol),inv2),lenrow))%=mod;
		};
		solve(0),solve(1);
		cout<<ans<<endl;
	}
	return 0;
}
posted @ 2023-03-01 16:15  曹轩鸣  阅读(56)  评论(0)    收藏  举报