2026-03-26 ZYZ28-CSP-XiaoMao Round 2 hetao1733837 的 record
开的时候只有 30min 了,未能完成对 T1 的 AC。
T1.ovo
原题链接:都快忘了怎样恋一个爱(ovo)
分析
太耻辱了/ll
bur,我认为我的 T1 实现了正解应该实现的功能,但是,显然没有过/ll
显然第一遍没有读懂题,题目是任意子矩形的由左上到右下的对角线,所以,只要这个对角线上是对的,就可以。
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1005, M = 100005;
int n, a[N][N], b[N][N];
int cnt[M];
signed main(){
freopen("ovo.in", "r", stdin);
freopen("ovo.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
cin >> a[i][j];
}
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
cin >> b[i][j];
}
}
for (int i = 2; i <= (n << 1); i++){
int tot = 0;
for (int j = max(i - n, 1); j <= min(i, n); j++){
tot += (!cnt[a[i - j][j]]);
cnt[a[i - j][j]]++;
}
for (int j = max(i - n, 1); j <= min(i, n); j++){
cnt[b[i - j][j]]--;
tot -= (!cnt[b[i - j][j]]);
}
if (tot){
cout << "No";
return 0;
}
}
cout << "Yes";
}
T2.wmrqwq
分析
我好像会了。
就是说,对于每个数,我们做一下质因数分解......反正这个东西和树状数组确实关系密切,但是,我不会......
咦?我会了吗?
被 #define int long long 做局了/ll
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int read(){
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-'){
f = -1;
}
c = getchar();
}
while(c >= '0' && c <= '9'){
x = x * 10 + (c - '0');
c = getchar();
}
return x * f;
}
int lowbit(int x){
return x & (-x);
}
int c[N];
void add(int x){
for (int i = x; i <= 200000; i += lowbit(i))
c[i]++;
return ;
}
int query(int x){
int res = 0;
for (int i = x; i; i -= lowbit(i))
res += c[i];
return res;
}
long long ans;
void solve(int x){
int l = 1, r = 0;
while (l <= x){
r = x / (x / l);
ans += 1ll * (query(r) - query(l - 1)) * (x / l);
l = r + 1;
}
return ;
}
int n, a;
signed main(){
freopen("wmrqwq.in", "r", stdin);
freopen("wmrqwq.out", "w", stdout);
n = read();
for(int i = 1; i <= n; i++){
a = read();
add(a);
solve(a);
}
cout << ans;
return 0;
}
T3.ono
原题链接:就让我陪他恋完这场爱(ono)
分析
注意到,选一个数,似乎只有相邻一个数的限制。那么,这个题似乎有一定的......可操作空间。
咦,想想是否有无后效性?这样似乎可以写成一个 O ( n 2 ) O(n^2) O(n2) 的 dp 。
还是先想一个绝对暴力的东西,设 d p i , j dp_{i,j} dpi,j 表示考虑了前 i i i 个位置,第 i i i 个位置的值为 j j j 时的方案数,这样,可以粗略得出转移方程
d p i , j = ∑ o = 1 j d p i − 1 , o + ∑ o = 1 k ( d p i − 1 , o × [ o mod j ≠ 0 ] ) dp_{i,j}=\sum\limits_{o=1}^{j}{dp_{i-1,o}}+\sum\limits_{o=1}^{k}{(dp_{i-1,o}\times[o\operatorname{mod} j \neq 0])} dpi,j=o=1∑jdpi−1,o+o=1∑k(dpi−1,o×[omodj=0])
复杂度大概是 O ( n k 2 ) O(nk^2) O(nk2) 左右?试一下,大概有 20 p t s 20pts 20pts 左右。
咦?为何 WA ?
好吧,算重了一坨。
严肃决定明天再补。
开始吧!
喔!求合法的不就是求不合法的吗?hxf 容斥还在追我!
那么,就是求满足 a i > a i + 1 a_i>a_{i+1} ai>ai+1 且 a i + 1 ∣ a i a_{i+1}|a_i ai+1∣ai 的序列个数,将其定义为"整除序列"。
设 g i g_i gi 表示值域内长度为 i i i 的整除序列数量。
设 h i h_i hi 表示长度为 i i i 的合法序列的数量。
则
h i = ∑ j = 0 i − 1 ( − 1 ) i − j h j g i − j h_i=\sum\limits_{j=0}^{i-1}{(-1)^{i-j}h_jg_{i-j}} hi=j=0∑i−1(−1)i−jhjgi−j
复杂度其实是对的。
正解
cpp
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
const int N = 500005;
int n, k, len[N], g[N], h[N], cnt;
vector<int> f[N], gr[N];
void calc(int &x, int y){
x = (x + y) % mod;
}
signed main(){
freopen("ono.in", "r", stdin);
freopen("ono.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= k; i++)
for (int j = i; j <= k; j += i)
gr[j].push_back(i);
for (int i = 1; i <= k; i++){
len[i] = 1;
for (auto x : gr[i])
if (x != i)
len[i] = max(len[i], len[x] + 1);
f[i].resize(len[i] + 1);
f[i][1] = 1;
for (auto x : gr[i]){
if(x == i)
continue;
for (int l = 0; l <= len[x]; l++){
calc(f[i][l + 1], f[x][l]);
cnt++;
}
}
for (int j = 0; j <= len[i]; j++)
calc(g[j], f[i][j]);
}
h[0] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= min(i, 25); j++)
calc(h[i], 1ll * h[i - j] * g[j] % mod * ((j & 1) ? 1 : -1) % mod);
cout << (h[n] + mod) % mod;
return 0;
}
T4.philiamono
原题链接:LYX 最喜欢的数据结构题(philiamono)
分析
复杂度放了 O ( r c ) O(rc) O(rc)......
应该有一个扫描线,然后拿一个前缀和乱搞一下?
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3005;
int r, c, n, k, x[N], y[N], p[N], nxt[N], lst[N], arv[N], prv[N];
int tmp, res, cnt[N];
vector<int> vec[N], vg;
int calc(int p){
if(p < 1 || arv[p] < 1)
return 0;
return (p - lst[p]) * (c - arv[p] + 1);
}
void ers(int x){
if (cnt[x] == 1){
tmp -= calc(x);
tmp -= calc(nxt[x]);
}
for (int i = x, c = 0; i > 0; i = lst[i]){
if (i != x)
c += cnt[i];
if (c >= k)
break;
prv[i]--;
if (prv[i] < 0 && arv[i] != -1){
if (!(i == x && cnt[x] == 1))
tmp -= calc(i);
arv[i] = nxt[arv[i]];
if (arv[i] != -1)
prv[i] = cnt[arv[i]] - 1;
if (!(i == x && cnt[x] == 1))
tmp += calc(i);
}
}
if (cnt[x] == 1){
if (lst[x] != -1)
nxt[lst[x]] = nxt[x];
if (nxt[x] != -1)
lst[nxt[x]] = lst[x];
tmp += calc(nxt[x]);
arv[x] = lst[x] = nxt[x] = -1;
}
return ;
}
signed main(){
freopen("philiamono.in", "r", stdin);
freopen("philiamono.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> r >> c >> n >> k;
for (int i = 1; i <= n; i++){
cin >> x[i] >> y[i];
vec[x[i]].push_back(y[i]);
}
for (int i = 1; i <= r; i++)
sort(vec[i].begin(), vec[i].end());
for (int i = 1; i <= r; i++){
tmp = 0;
for (int j = 0; j <= max(n, max(r, c)); j++){
nxt[j] = lst[j] = -1;
arv[j] = -1;
cnt[j] = prv[j] = 0;
}
vg.clear();
for (int j = 1; j <= n; j++){
if (x[j] < i)
continue;
if (!cnt[y[j]]++)
vg.push_back(y[j]);
}
vg.push_back(0);
sort(vg.begin(), vg.end());
for (int j = 0; j < (int) vg.size(); j++){
if (j < (int) vg.size() - 1){
nxt[vg[j]] = vg[j + 1];
lst[vg[j + 1]] = vg[j];
}
}
for (int j = 1; j < (int) vg.size(); j++){
for (int p = vg[j], c = 0; p >= 1; p = nxt[p]){
c += cnt[p];
if (c >= k){
arv[vg[j]] = p;
prv[vg[j]] = c - k;
break;
}
}
tmp += calc(vg[j]);
}
for (int j = r; j >= i; j--){
if (tmp < 0)
break;
res += tmp;
for (auto pj : vec[j]){
ers(pj);
cnt[pj]--;
}
}
}
cout << res;
}