[ABC269F] Numbered Checker 题解
[ABC269F] Numbered Checker Solution
更好的阅读体验戳此进入
题面
存在 $ n \times m $ 的网格图,在里面按照从左至右,从上至下的顺序填写 $ [1, n \times m] $ 所有数,然后使所有行数与列数之和为奇数的格子中的数推平为 $ 0 \(。\) q $ 次询问求子矩形权值和。
Solution
尝试简单推一下式子,显然对于奇数行,为 $ 1 + km, 3 + km, 5 + km, \cdots $,偶数行同理。对于多行相加,奇数行则 $ k = 0, 2, 4, \cdots $,偶数行同理。也就是说我们讨论奇偶之后,对一行里做一下等差数列求和然后乘上奇数行行数,对 $ k $ 做一遍等差数列求和然后乘上奇数列列数和 $ m $ 即可。
同时注意对于偶数的求和需要全部转为偶数,反之全部转为奇数。
同时也可以用简单的容斥思想,每次计算左上角为 $ 1 $ 的四个矩形的值并处理,但实现难度与此方法接近。
同时整个过程中仅需 long long
即可,等差数列求和的除以 $ 2 $ 不需要用逆元,适当取模后也不需要用 __int128_t
。
Code
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;
#define MOD (998244353ll)
template < typename T = int >
inline T read(void);
int N, M;
ll QueryOdd(ll l, ll r){
if(!(l & 1))++l;
if(!(r & 1))--r;
if(l > r)return 0;
return (((l + r) * (((r - l) >> 1) + 1)) >> 1) % MOD;
}
ll QueryEven(ll l, ll r){
if(l & 1)++l;
if(r & 1)--r;
if(l > r)return 0;
return (((l + r) * (((r - l) >> 1) + 1)) >> 1) % MOD;
}
ll CntOdd(ll l, ll r){
if(!(l & 1))++l;
if(!(r & 1))--r;
if(l > r)return 0;
return (((r - l) >> 1) + 1) % MOD;
}
ll CntEven(ll l, ll r){
if(l & 1)++l;
if(r & 1)--r;
if(l > r)return 0;
return (((r - l) >> 1) + 1) % MOD;
}
int main(){
N = read(), M = read();
int Q = read();
while(Q--){
ll ans(0);
int a = read(), b = read(), c = read(), d = read();
(ans += QueryOdd(c, d) * CntOdd(a, b) % MOD) %= MOD;
(ans += ((QueryOdd(a, b) - CntOdd(a, b) + MOD) % MOD) * CntOdd(c, d) % MOD * M % MOD) %= MOD;
(ans += QueryEven(c, d) * CntEven(a, b) % MOD) %= MOD;
(ans += ((QueryEven(a, b) - CntEven(a, b) + MOD) % MOD) * CntEven(c, d) % MOD * M % MOD) %= MOD;
printf("%lld\n", ans);
}
fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
template < typename T >
inline T read(void){
T ret(0);
int flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
UPD
update-2023_01_25 初稿