Codeforces Round 869 (Div.1 & Div.2) 题解
https://codeforces.com/contest/1817
https://codeforces.com/contest/1818
2A. Politics
因为编号为
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read () {
int x = 0, f = 0;
char c = getchar ();
for ( ; c < '0' || c > '9' ; c = getchar ()) f |= (c == '-');
for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
}
char s[105][105];
int n, k;
signed main () {
int _ = read ();
while (_ --) {
n = read (), k = read ();
for (int i = 1;i <= n; ++ i) scanf ("%s", s[i] + 1);
int ans = 1;
for (int i = 2;i <= n; ++ i) {
int ok = 1;
for (int j = 1;j <= k; ++ j) {
if (s[i][j] != s[1][j]) ok = 0;
}
ans += ok;
}
printf ("%d\n", ans);
}
return 0;
}
2B. Indivisible
我们可以写一个
然后分成两种情况:
-
如果
,那么答案为 。 -
否则答案为
。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read () {
int x = 0, f = 0;
char c = getchar ();
for ( ; c < '0' || c > '9' ; c = getchar ()) f |= (c == '-');
for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
}
int a[105], _, n, sum[105];
signed main () {
_ = read ();
while (_ --) {
n = read ();
if (n == 1) {
printf ("1\n");
continue;
}
if (n & 1) {
printf ("-1\n");
continue;
}
for (int i = 1, j = 2;i <= n; i += 2, j += 2) a[i] = j;
for (int i = 2;i <= n; i += 2) a[i] = a[i - 1] - 1;
for (int i = 1;i <= n; ++ i) printf ("%d ", a[i]);
printf ("\n");
}
return 0;
}
2C/1A. Almost Increasing Subsequence
我们首先考虑长度为
我们要把满足
直接前缀和即可。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read () {
int x = 0, f = 0;
char c = getchar ();
for ( ; c < '0' || c > '9' ; c = getchar ()) f |= (c == '-');
for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
}
int n, q, a[200005], s[200005];
signed main () {
n = read (), q = read ();
for (int i = 1;i <= n; ++ i) a[i] = read ();
for (int i = 1;i <= n; ++ i) {
s[i] = s[i - 1];
if (a[i] >= a[i + 1] && a[i + 1] >= a[i + 2] && i + 2 <= n) s[i] ++;
}
while (q --) {
int l = read (), r = read (), ans = r - l + 1;
int L = l, R = r - 2;
if (L <= R) {
int d = s[R] - s[L - 1];
ans -= d;
}
printf ("%d\n", ans);
}
return 0;
}
2D/1B. Fish Graph
我们考虑将每一个连通块分开处理,对于每一个连通块,取出其中任意一个生成树,拎出来每一个非树边,然后就构成了一个环,枚举每一个点(是点
代码非常难写,有 114514 个细节,需要注意。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read () {
int x = 0, f = 0;
char c = getchar ();
for ( ; c < '0' || c > '9' ; c = getchar ()) f |= (c == '-');
for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
}
const int N = 2005;
struct LCAns {
struct edge {int to, nxt;} e[N << 1];
int head[N], eid;
inline void add_edge (int u, int v) {e[eid] = {v, head[u]}; head[u] = eid ++;}
int dp[N][17], d[N], lg[N];
int n, root;
inline void dfs (int u) {
for (int i = head[u]; ~i ; i = e[i].nxt) {
int v = e[i].to;
if (v == dp[u][0]) continue;
dp[v][0] = u; d[v] = d[u] + 1; dfs (v);
}
}
inline int LCA (int u, int v) {
if (d[u] < d[v]) swap (u, v);
for (int j = lg[d[u] - d[v]];j >= 0; -- j) {if (d[dp[u][j]] >= d[v]) u = dp[u][j];}
if (u == v) return u;
for (int j = lg[d[u]];j >= 0; -- j) {if (dp[u][j] != dp[v][j]) {u = dp[u][j], v = dp[v][j];}}
return dp[u][0];
}
inline void perf () {
for (int i = 0;i < N; ++ i) head[i] = -1;
eid = 0;
}
inline void pre () {
lg[0] = -1;
for (int i = 1;i <= n; ++ i) dp[i][0] = 0, d[i] = 0;
for (int i = 1;i <= n; ++ i) lg[i] = lg[i / 2] + 1;
d[root] = 1; dfs (root);
for (int j = 1; (1 << j) < n; ++ j) for (int i = 1;i <= n; ++ i) {
dp[i][j] = dp[dp[i][j - 1]][j - 1];
}
}
} tr;
int ed[N][2], n, m, vis[N], vis2[N], fl[N];
struct DSU {
int fa[N];
inline void init (int X) {
for (int i = 1;i <= X; ++ i) fa[i] = i;
}
inline int find (int x) {
return fa[x] == x ? x : fa[x] = find (fa[x]);
}
inline void merge (int x, int y) {
fa[find (x)] = find (y);
}
inline int query (int x, int y) {
return find (x) == find (y);
}
} awa, qwq;
vector < pair < int, int > > th;
vector < int > G2[N], G[N];
signed main () {
int _ = read ();
while (_ --) {
n = read (), m = read ();
for (int i = 1;i <= n; ++ i) vis[i] = 0;
for (int i = 1;i <= m; ++ i) vis2[i] = 0;
awa.init (n);
for (int i = 1;i <= m; ++ i) {
ed[i][0] = read (), ed[i][1] = read ();
awa.merge (ed[i][0], ed[i][1]);
G[ed[i][0]].push_back (ed[i][1]);
G[ed[i][1]].push_back (ed[i][0]);
}
int ok = 0;
for (int i = 1;i <= n; ++ i) {
if (vis[i]) continue;
tr.n = n, tr.root = i;
tr.perf ();
vector < int > _edge, ex;
_edge.clear ();
ex.clear ();
qwq.init (n);
for (int j = 1;j <= m; ++ j) {
if (!awa.query (i, ed[j][0]) || !awa.query (i, ed[j][1])) continue;
if (qwq.query (ed[j][0], ed[j][1])) {
ex.push_back (j);
continue;
}
tr.add_edge (ed[j][0], ed[j][1]);
tr.add_edge (ed[j][1], ed[j][0]);
G2[ed[j][0]].push_back (ed[j][1]);
G2[ed[j][1]].push_back (ed[j][0]);
vis2[j] = 1;
vis[ed[j][0]] = vis[ed[j][1]] = 1;
_edge.push_back (j);
qwq.merge (ed[j][0], ed[j][1]);
}
tr.pre ();
for (int E : ex) {
int U = ed[E][0], V = ed[E][1];
int Z = tr.LCA (U, V);
for (int j = 1;j <= n; ++ j) fl[j] = 1;
vector < int > vertex;
vertex.clear ();
int tot = 1;
for (int j = U; j != Z; j = tr.dp[j][0]) vertex.push_back (j), tot ++;
for (int j = V; j != Z; j = tr.dp[j][0]) vertex.push_back (j), tot ++;
vertex.push_back (Z);
for (int u : vertex) fl[u] = 0;
for (int u : vertex) {
th.clear ();
for (int v : G[u]) {
if (fl[v]) th.push_back (make_pair (u, v));
}
if (th.size () >= 2) {
tot += 2;
printf ("YES\n");
ok = 1;
printf ("%d\n", tot);
for (int j = U; j != Z; j = tr.dp[j][0]) printf ("%d %d\n", j, tr.dp[j][0]);
for (int j = V; j != Z; j = tr.dp[j][0]) printf ("%d %d\n", j, tr.dp[j][0]);
printf ("%d %d\n", U, V);
printf ("%d %d\n", th[0].first, th[0].second);
printf ("%d %d\n", th[1].first, th[1].second);
break;
}
}
if (ok) break;
}
for (int j = 1;j <= n; ++ j) G2[j].clear ();
if (ok) break;
}
if (!ok) printf ("NO\n");
for (int i = 1;i <= n; ++ i) G[i].clear ();
}
return 0;
}
2E/1C. Similar Polynomials
首先我们设:
我们要让
发现永远不会变。
然后我们要让
发现会对
然后就爆算:
由此可得:
然后就是拉格朗日插值求出
拉格朗日插值的式子:
常数项就不用理会了,因为乘起来的贡献为
同理:
然后就是爆算:
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read () {
int x = 0, f = 0;
char c = getchar ();
for ( ; c < '0' || c > '9' ; c = getchar ()) f |= (c == '-');
for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
}
const int mod = 1e9 + 7;
const int N = 2.5e6 + 5;
inline int pow_mod (int a, int b, int p) {
int res = 1;
while (b) {
if (b & 1) res = res * a % p;
b >>= 1, a = a * a % p;
}
return res;
}
int d, A[N], B[N], coefA[2], coefB[2], fac[N], ifac[N];
signed main () {
d = read ();
fac[0] = 1;
for (int i = 1;i < N; ++ i) fac[i] = fac[i - 1] * i % mod;
ifac[N - 1] = pow_mod (fac[N - 1], mod - 2, mod);
for (int i = N - 2;i >= 0; -- i) ifac[i] = ifac[i + 1] * (i + 1) % mod;
for (int i = 0;i <= d; ++ i) A[i] = read ();
for (int i = 0;i <= d; ++ i) B[i] = read ();
for (int i = 0;i <= d; ++ i) {
int dx = ifac[i] * ifac[d - i] % mod;
if ((d - i) & 1) dx = mod - dx;
if (dx >= mod) dx -= mod;
dx = dx * A[i] % mod;
coefA[1] = (coefA[1] + dx) % mod;
}
for (int i = 0;i <= d; ++ i) {
int dx = ifac[i] * ifac[d - i] % mod;
if ((d - i) & 1) dx = mod - dx;
if (dx >= mod) dx -= mod;
dx = dx * B[i] % mod;
coefB[1] = (coefB[1] + dx) % mod;
}
for (int i = 0;i <= d; ++ i) {
int dx = ifac[i] * ifac[d - i] % mod;
if ((d - i) & 1) dx = mod - dx;
if (dx >= mod) dx -= mod;
dx = dx * A[i] % mod;
int coef = d * (d + 1) / 2 - i;
coef %= mod;
dx = dx * coef % mod;
coefA[0] = (coefA[0] + dx) % mod;
}
for (int i = 0;i <= d; ++ i) {
int dx = ifac[i] * ifac[d - i] % mod;
if ((d - i) & 1) dx = mod - dx;
if (dx >= mod) dx -= mod;
dx = dx * B[i] % mod;
int coef = d * (d + 1) / 2 - i;
coef %= mod;
dx = dx * coef % mod;
coefB[0] = (coefB[0] + dx) % mod;
}
coefA[0] = mod - coefA[0], coefA[0] %= mod;
coefB[0] = mod - coefB[0], coefB[0] %= mod;
int ans = coefB[1] * d % mod;
ans = pow_mod (ans, mod - 2, mod);
int coef = coefB[0] - coefA[0];
coef = (coef % mod + mod) % mod;
ans = ans * coef % mod;
printf ("%lld\n", ans);
return 0;
}
2F/1D. Toy Machine
对于中间的方块的编号设为
对于所有 LDRU
即可,最后再做一遍
对于 DL
,为什么自己想。
对于
确定一个数据:15 10
。
- Step
:
中间的 g
有点烦人,先移走:
- Step
:
可以用中间的黑块卡住一个方块,剩下的整体向下,操作序列为 ULDL
。
- Step
:
在保留顺序的情况下将方块卡到右半边:
因为要保留顺序,所以先整体向右:
然后就是按 URDR
的顺序一个个移到右半边,正确性显然。
- Step
:
出答案。
将填充好的上边移动到左边,然后就按照
最后就是这个效果:
代码比较简单,但是需要自己计算。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
inline int read () {
int x = 0, f = 0;
char c = getchar ();
for ( ; c < '0' || c > '9' ; c = getchar ()) f |= (c == '-');
for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c & 15);
return !f ? x : -x;
}
signed main () {
int n = read (), k = read (), num = n - 2, mid = (num + 1) / 2;
if (k < mid) {
for (int i = 1;i < k; ++ i) printf ("LDRU");
printf ("L\n");
}
else if (k == mid) printf ("DL\n");
else {
printf ("DL");
for (int i = mid + 1;i <= k; ++ i) printf ("ULDL");
printf ("R");
for (int i = 1;i <= num - (mid + 1) + 1; ++ i) printf ("URDR");
printf ("L");
for (int i = 1;i < mid; ++ i) printf ("LDRU");
printf ("L\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下