概述
K题意
在二维坐标系上给出一些圆和正方形,把他们涂黑,求所有图形的周长和。
思路
- 有负数坐标,先加一个数字映射到正数域
- 直线直接枚举,看方格的位置关系,注意细节
- 曲线枚举格子的情况,看在这个格子里有多少 1 4 frac{1}{4} 41圆就知道这个格子里曲线的长度
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int dirt = 1e2 + 5;
const int Max = 3e2 + 5;
const int mod = 998244353;
const int inv6 = 166374059;
int sq[Max][Max], cir[Max][Max], e[Max][Max][8];
int ans1 = 0, ans2 = 0, n;
const int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
const int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
const int ddx[] = {1, 2, 2, 1, -1, -2, -2, -1};
const int ddy[] = {2, 1, -1, -2, -2, -1, 1, 2};
int have(int x, int y) {
return sq[x][y] || cir[x][y];
}
int cover(int x, int y) {
if(sq[x][y] || sq[x + 1][y] || sq[x + 1][y + 1] || sq[x][y + 1]) return 1;
if(cir[x][y] && cir[x + 1][y + 1]) return 1;
if(cir[x + 1][y] && cir[x][y + 1]) return 1;
return 0;
}
int main() {
set<pair<pii, pii>> st;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int op, x, y;
scanf("%d %d %d", &op, &x, &y);
x += dirt, y += dirt;
if(op == 1) {
sq[x][y] = 1;
for(int j = 0; j < 8; j++) e[x][y][j] = 1;
}
else {
cir[x][y] = 1;
}
}
for(int i = 2; i < Max - 2; i++) {
for(int j = 2; j < Max - 2; j++) {
if(sq[i][j] && sq[i][j + 2]) e[i][j][0] = e[i][j][7] = 0;
if(sq[i][j] && sq[i + 2][j]) e[i][j][1] = e[i][j][2] = 0;
if(sq[i][j] && sq[i][j - 2]) e[i][j][3] = e[i][j][4] = 0;
if(sq[i][j] && sq[i - 2][j]) e[i][j][5] = e[i][j][6] = 0;
for(int k = 0; k < 8; k++) {
if(e[i][j][k] && (have(i + dx[k], j + dy[k]) || have(i + dx[(k + 1) % 8], j + dy[(k + 1) % 8]) || sq[i + ddx[k]][j + ddy[k]]))
e[i][j][k] = 0;
if(e[i][j][k]) {
auto u = pair<int, int>(i + dx[k], j + dy[k]), v = pair<int, int>(i + dx[(k + 1) % 8], j + dy[(k + 1) % 8]);
if(u > v) swap(u, v);
st.insert({u, v});
}
}
}
}
for(int i = 0; i < Max - 1; i++) {
for(int j = 0; j < Max - 1; j++) {
if(cover(i, j)) continue;
if(cir[i][j] + cir[i + 1][j] + cir[i + 1][j + 1] + cir[i][j + 1] == 1) ans2 += 3;
if(cir[i][j] + cir[i + 1][j] + cir[i + 1][j + 1] + cir[i][j + 1] == 2) ans2 += 2;
}
}
printf("%d %lldn", (int)st.size(), 1ll * ans2 * inv6 % mod);
return 0;
}
L题意
给出一个字符串,再给出区间 [ l i , r i ] [l_i,r_i] [li,ri]的生成算法,求 [ l i , r i ] [l_i,r_i] [li,ri]中有多少个ICPC子序列
思路
容斥, X [ i ] X[i] X[i]的定义为到 i i i为止 X X X序列出现的次数,因为ICPC=I+CPC或者IC+PC或者ICP+C,所以我们从大到小计算每个序列的合法数量进行容斥即可
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int Maxn = 2e6 + 7;
constexpr int Mod = 998244353;
// assume -P <= x < 2P
int norm(int x) {if(x < 0)x += Mod;if (x >= Mod)x -= Mod;return x;}
template<class T>T power(T a, int b){T res = 1;for (; b; b /= 2, a *= a)if (b & 1)res *= a;return res;}
struct Mint {
int x;Mint(int x = 0) : x(norm(x)){}
int val() const {return x;}
Mint operator-() const {return Mint(norm(Mod - x));}
Mint inv() const {assert(x != 0);return power(*this, Mod - 2);}
Mint &operator*=(const Mint &rhs) { x = ll(x) * rhs.x % Mod; return *this;}
Mint &operator+=(const Mint &rhs) { x = norm(x + rhs.x); return *this;}
Mint &operator-=(const Mint &rhs) { x = norm(x - rhs.x); return *this;}
Mint &operator/=(const Mint &rhs) {return *this *= rhs.inv();}
friend Mint operator*(const Mint &lhs, const Mint &rhs) {Mint res = lhs; res *= rhs; return res;}
friend Mint operator+(const Mint &lhs, const Mint &rhs) {Mint res = lhs; res += rhs; return res;}
friend Mint operator-(const Mint &lhs, const Mint &rhs) {Mint res = lhs; res -= rhs; return res;}
friend Mint operator/(const Mint &lhs, const Mint &rhs) {Mint res = lhs; res /= rhs; return res;}
};
char s[Maxn];
Mint I[Maxn], C[Maxn], P[Maxn], IC[Maxn], CP[Maxn], PC[Maxn], ICP[Maxn], CPC[Maxn], ICPC[Maxn];
Mint get_PC(int l, int r) {
return PC[r] - PC[l - 1] - P[l - 1] * (C[r] - C[l - 1]);
}
Mint get_CPC(int l, int r) {
return CPC[r] - CPC[l - 1]
- CP[l - 1] * (C[r] - C[l - 1])
- C[l - 1] * get_PC(l, r);
}
Mint get_ICPC(int l, int r) {
return ICPC[r] - ICPC[l - 1]
- ICP[l - 1] * (C[r] - C[l - 1])
- IC[l - 1] * get_PC(l, r)
- I[l - 1] * get_CPC(l, r);
}
int32_t main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, q;
cin >> n >> q >> s + 1;
ll x, a, b, p;
cin >> x >> a >> b >> p;
for(int i = 1; i <= n; i++) {
I[i] = I[i - 1], C[i] = C[i - 1], P[i] = P[i - 1];
IC[i] = IC[i - 1], CP[i] = CP[i - 1], PC[i] = PC[i - 1];
ICP[i] = ICP[i - 1], CPC[i] = CPC[i - 1], ICPC[i] = ICPC[i - 1];
if(s[i] == 'I') {
I[i] += 1;
}
if(s[i] == 'C') {
C[i] += 1;
IC[i] += I[i - 1];
PC[i] += P[i - 1];
CPC[i] += CP[i - 1];
ICPC[i] += ICP[i - 1];
}
if(s[i] == 'P') {
P[i] += 1;
CP[i] += C[i - 1];
ICP[i] += IC[i - 1];
}
}
Mint ans = 0;
vector<int> l(q), r(q);
for(int i = 0; i < q; i++) {
x = (a * x + b) % p;
l[i] = x % n;
l[i] += 1;
}
for(int i = 0; i < q; i++) {
x = (a * x + b) % p;
r[i] = x % n;
r[i] += 1;
if(l[i] > r[i]) swap(l[i], r[i]);
ans += get_ICPC(l[i], r[i]);
}
cout << ans.val() << 'n';
return 0;
}
最后
以上就是认真云朵为你收集整理的2022ICPC网络赛预选赛第二场题解,K题L题K题意L题意的全部内容,希望文章能够帮你解决2022ICPC网络赛预选赛第二场题解,K题L题K题意L题意所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复