2026.7.10 核桃彩虹周赛119总结
省流:100 + 100 + 100 + 100 + 25 + 0
T1 填充
有一个 \(n \times m\) 的网格,你可以拿 \(3 \times 3\) 或者 \(2 \times 2\) 的矩形去覆盖它,两两之间不能有重叠,问是否能完全覆盖这个网格。
注意到 \(\gcd(2,3) = 6\),所以做完了。
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
//const int M = ;
int read(){
int sgn = 1, ans = 0;
char c = getchar();
while(!isdigit(c)){
if(c == '-') sgn = -sgn;
c = getchar();
}
while(isdigit(c)) ans = ans * 10 + c - '0', c = getchar();
return sgn * ans;
}
void sol(){
int n = read(), m = read();
if(n < 2 || m < 2) cout << "NO\n";
else if(n % 2 == 0 && m % 2 == 0) cout << "YES\n";
else if(n % 3 == 0 && m % 3 == 0) cout << "YES\n";
else if(n % 6 == 0 || m % 6 == 0) cout << "YES\n";
else cout << "NO\n";
}
signed main(){
int T = read();
while(T--) sol();
return 0;
}
T2 抛物线
给定 \(n\) 个抛物线以及 \(m\) 条直线,你需要求有多少对 \((a,A,B)\) 满足:
直线 \(A \neq B\) 存在交点且交点与抛物线 \(a\) 的顶点不重合且所连直线垂直于 \(x\) 轴。
按照题意枚举即可。
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const double eps = 1e-10;
const int M = 105;
struct n1{
double a, b, c;
}arr[M];
struct n2{
double k, b;
}brr[M];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> arr[i].a >> arr[i].b >> arr[i].c;
}
for(int i = 1; i <= m; i++) {
cin >> brr[i].k >> brr[i].b;
}
int tot = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
for(int r = j + 1; r <= m; r++) {
double x = (brr[j].b - brr[r].b) / (brr[r].k - brr[j].k);
double y = brr[j].k * x + brr[j].b;
double xx = -arr[i].b / 2 / arr[i].a;
double yy = arr[i].a * xx * xx + arr[i].b * xx + arr[i].c;
if(x == xx && y != yy) tot++;
}
}
}
cout << tot * 2;
return 0;
}
T3 乘数
给定一个非负整数 \(n\),你需要将 \(n\) 乘以某个正整数,假设乘后的数字是 \(x\),则你需要保证:
-
\(x\) 去掉末尾连续 \(0\) 后的位数 \(s_1\) 最小。
-
保证 \(s_1\) 最小的前提下,\(x\) 的位数 \(s_2\) 最小。
显然我们会发现 \(n\) 中所有的因子 \(2,5\) 都会被转化为 \(10\) 丢掉。所以最后得到的数就是 \(n\) 去除因子 \(2,5\) 剩下的数,假设值为 \(n'\)。
然后我们最小化 \(s_2\),显然我们在不影响 \(n'\) 的位数下要尽量少除 \(2,5\)。所以我们可以枚举 \(n' \times 2,4,5,8\),看是否会进位,如果不会则更新答案。
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){
int sgn = 1, ans = 0;
char c = getchar();
while(!isdigit(c)){
if(c == '-') sgn = -sgn;
c = getchar();
}
while(isdigit(c)) ans = ans * 10 + c - '0', c = getchar();
return sgn * ans;
}
int dv(int &x, int y) {
int tot = 0;
while(x % y == 0) {
x /= y;
++tot;
}
return tot;
}
void sol() {
int n = read();
if(n == 0) {
cout << "1 1\n";
return;
}
int a = dv(n, 2), b = dv(n, 5), c = n;
int s1 = to_string(c).size();
int s2 = max(a, b) + s1;
for(int i = 1; i <= 3; i++) {
int tmp = c * (1 << i);
if(to_string(tmp).size() == s1) {
int k = max(a - i, b);
s2 = min(s2, k + s1);
}
}
int tmp = c * 5;
if(to_string(tmp).size() == s1) {
int k = max(a, b - 1);
s2 = min(s2, k + s1);
}
cout << s1 << ' ' << s2 << '\n';
}
signed main(){
int T = read();
while(T--) sol();
return 0;
}
T4 等差
给定一个长度为 \(n\) 的数列 \(a\),保证 \(n\) 为偶数。
你需要在这个数列中添加一个整数 \(x\),使得新数列的众数、中位数、平均数可以排列成一个等差数列;保证添加前和添加后众数都唯一。求出可能的 \(x\)。
显然众数不会变,可以直接求出来。
然后添加一个数后,中位数只会有三种可能: \(a_{n/2}, a_{n / 2 + 1},x\)。直接大力枚举 \(9\) 种情况,直接计算即可。
代码很长可读性较差,可能算一种大模拟吧。
code
#include <bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int sgn = 1, ans = 0;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') sgn = -sgn;
c = getchar();
}
while (isdigit(c)) ans = ans * 10 + c - '0', c = getchar();
return sgn * ans;
}
bool chk(int a, int b, int c) {
if (2 * a == b + c) return true;
if (2 * b == a + c) return true;
if (2 * c == a + b) return true;
return false;
}
void sol() {
int n = read();
vector<int> a(n);
int sum = 0;
map<int, int> fr;
for (int i = 0; i < n; i++) {
a[i] = read();
sum += a[i];
fr[a[i]]++;
}
int m0 = a[0], f0 = fr[a[0]];
for (auto &p : fr) {
if (p.second > f0) {
f0 = p.second;
m0 = p.first;
}
}
unordered_set<int> d;
for (auto &p : fr) {
if (p.second == f0 - 1) d.insert(p.first);
}
sort(a.begin(), a.end());
int k = n / 2;
int L = a[k - 1], R = a[k];
int N = n + 1;
int S = sum;
set<int> ans;
auto ck = [&](int x) -> bool {
if (x == m0) return true;
return d.find(x) == d.end();
};
auto add = [&](int x, int med) {
if (!ck(x)) return;
if ((S + x) % N != 0) return;
int avg = (S + x) / N;
if (chk(m0, med, avg)) ans.insert(x);
};
int avg1 = 2 * m0 - L;
int x1 = N * avg1 - S;
if (x1 <= L) add(x1, L);
int avg2 = 2 * L - m0;
int x2 = N * avg2 - S;
if (x2 <= L) add(x2, L);
if ((m0 + L) % 2 == 0) {
int avg3 = (m0 + L) / 2;
int x3 = N * avg3 - S;
if (x3 <= L) add(x3, L);
}
int avg7 = 2 * m0 - R;
int x7 = N * avg7 - S;
if (x7 >= R) add(x7, R);
int avg8 = 2 * R - m0;
int x8 = N * avg8 - S;
if (x8 >= R) add(x8, R);
if ((m0 + R) % 2 == 0) {
int avg9 = (m0 + R) / 2;
int x9 = N * avg9 - S;
if (x9 >= R) add(x9, R);
}
int num4 = 2 * m0 * N - S;
int den4 = N + 1;
if (num4 % den4 == 0) {
int x4 = num4 / den4;
if (x4 > L && x4 < R) add(x4, x4);
}
int num5 = m0 * N + S;
int den5 = 2 * N - 1;
if (num5 % den5 == 0) {
int x5 = num5 / den5;
if (x5 > L && x5 < R) add(x5, x5);
}
int num6 = 2 * S - N * m0;
int den6 = N - 2;
if (den6 != 0 && num6 % den6 == 0) {
int x6 = num6 / den6;
if (x6 > L && x6 < R) add(x6, x6);
}
cout << ans.size() << "\n";
for (int v : ans) cout << v << ' ';
cout << "\n";
}
signed main() {
int T = read();
while (T--) sol();
return 0;
}
T5 树上应聘
题意大概是求 $\sum\limits_{i=l_1}^{r_1} \sum\limits_{j=l_2}^{r_2} \left( \gcd\limits_{u \in \operatorname{path}(i, F(i, j))} w_u\right) $,其中 \(F(i,j)\) 表示 \(i\) 的 \(j\) 级祖先。

code
#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
#define ctz(x) __builtin_ctz(x)
#define popcnt(x) __builtin_popcount(x)
#define open(s1, s2) freopen(s1, "r", stdin), freopen(s2, "w", stdout);
using namespace std;
typedef __int128 __;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
const int N = 2e5 + 10, M = 1e6 + 10;
inline ll read(){
ll 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 << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int n, q, l1, r1, l2, r2;
vector<int> E[N];
inline void add(int u, int v){
E[u].push_back(v);
E[v].push_back(u);
}
namespace Seg{
struct Node{
int l, r;
int tag;
ll sum, hsum;
}X[N << 2];
inline void pushup(int k){
X[k].sum = X[k << 1].sum + X[k << 1 | 1].sum;
}
inline void add(int k, int v){
X[k].hsum += X[k].sum * v;
X[k].tag += v;
}
inline void push_down(int k){
if(X[k].tag){
add(k << 1, X[k].tag);
add(k << 1 | 1, X[k].tag);
X[k].tag = 0;
}
}
inline void build(int k, int l, int r){
X[k].l = l, X[k].r = r;
// cerr << k << ' ' << l << ' ' << r << '\n';
if(l == r)
return ;
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
}
inline void update(int k, int i, int v){
if(X[k].l == i && i == X[k].r){
X[k].sum = v;
return ;
}
push_down(k);
int mid = (X[k].l + X[k].r) >> 1;
if(i <= mid)
update(k << 1, i, v);
else
update(k << 1 | 1, i, v);
pushup(k);
}
inline ll ask(int k, int l, int r){
// cerr << k << ' ' << l << ' ' << r << ' ' << X[k].l << ' ' << X[k].r << '\n';
if(X[k].l == l && r == X[k].r)
return X[k].hsum;
push_down(k);
int mid = (X[k].l + X[k].r) >> 1;
if(r <= mid)
return ask(k << 1, l, r);
else if(l > mid)
return ask(k << 1 | 1, l, r);
else
return ask(k << 1, l, mid) + ask(k << 1 | 1, mid + 1, r);
}
}
int w[N], dep[N];
vector<pair<int, int>> V[N], T[N];
vector<pair<pair<int, int>, pair<int, int>>> Q[N];
ll ans[M];
inline void dfs(int u, int fa){
V[u].push_back({u, w[u]});
if(fa){
int pre = w[u];
for(auto t : V[fa]){
int now = __gcd(t.se, w[u]);
if(now == pre)
continue;
V[u].push_back({t.fi, now});
pre = now;
}
}
// cerr << u << ' ' << (int)V[u].size() << '\n';
for(auto v : E[u]){
if(v == fa)
continue;
dep[v] = dep[u] + 1;
dfs(v, u);
}
}
int main(){
// freopen("A.in", "r", stdin);
// freopen("A.out", "w", stdout);
n = read(), q = read();
// cerr << n << ' ' << q << '\n';
for(int i = 1; i <= n; ++i)
w[i] = read();
for(int u, v, i = 1; i < n; ++i){
u = read(), v = read();
add(u, v);
}
dfs(1, 0);
for(int u = 1; u <= n; ++u)
for(auto t : V[u])
T[dep[u] - dep[t.fi]].push_back({u, t.se});
for(int i = 1; i <= q; ++i){
l1 = read(), r1 = read(), l2 = read(), r2 = read();
Q[r2].push_back({{i, 1}, {l1, r1}});
if(l2)
Q[l2 - 1].push_back({{i, -1}, {l1, r1}});
}
Seg::build(1, 1, n);
for(int k = 0; k <= n; ++k){
for(auto t : T[k])
Seg::update(1, t.fi, t.se);
Seg::add(1, 1);
for(auto t : Q[k]){
// cerr << t.fi.fi << ' ' << t.se.fi << ' ' << t.se.se << '\n';
ans[t.fi.fi] += t.fi.se * Seg::ask(1, t.se.fi, t.se.se);
// cerr << "Yes\n";
}
}
for(int i = 1; i <= q; ++i){
write(ans[i]);
putchar('\n');
}
return 0;
}
T6 线段树测试
题目意思是给定一个序列,在上面建立线段树,有 \(q\) 次操作,每次随机选择一个区间 \([l, r] \subset[L_i, R_i]\) 加上一个整数 \(v \in [0, S]\),你需要在线段树上找到尽可能少的区间互不相交的线段树节点,使得它们区间的并集恰好是 \([l,r]\),然后将这些点的权值增加 \(v\)。最后求线段树上的所有节点的权值 \(k\) 次方的和。



code
#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
#define ctz(x) __builtin_ctz(x)
#define popcnt(x) __builtin_popcount(x)
#define open(s1, s2) freopen(s1, "r", stdin), freopen(s2, "w", stdout);
using namespace std;
typedef __int128 __;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
const int N = 1010, mod = 1e9 + 7;
inline ll read(){
ll 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 << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
inline void getadd(int &x, int y){
x = (x + y >= mod) ? (x + y - mod) : (x + y);
}
inline int add(int x, int y){
return (x + y >= mod) ? (x + y - mod) : (x + y);
}
inline void getdec(int &x, int y){
x = (x < y) ? (x - y + mod) : (x - y);
}
inline int dec(int x, int y){
return (x < y) ? (x - y + mod) : (x - y);
}
inline int qpow(int a, int b){
int ans = 1;
while(b){
if(b & 1)
ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return ans;
}
struct node{
int lson, rson;
int l, r;
vector<pair<int, int>> V;
}X[N << 2];
int n, q, k, S, L, R, rt, cnt, all, mul = 1, Ans;
int a[N], fac[N], ifac[N], F[N], G[N], H[N], fk[N];
int dp[2][N];
inline void init(){
fac[0] = fac[1] = 1;
for(int i = 2; i < N; ++i)
fac[i] = 1ll * i * fac[i - 1] % mod;
ifac[N - 1] = qpow(fac[N - 1], mod - 2);
for(int i = N - 2; i >= 0; --i)
ifac[i] = 1ll * (i + 1) * ifac[i + 1] % mod;
}
inline int get(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2){
int xL = max(x1, xx1);
int xR = min(y1, yy1);
if(xL > xR)
return 0;
int yB = max(x2, xx2), yT = min(y2, yy2);
if (yB > yT)
return 0;
return 1ll * (xR - xL + 1) * (yT - yB + 1) % mod;
}
inline void build(int &k, int l, int r){
k = ++cnt;
X[k].l = l, X[k].r = r;
X[k].V.push_back({0, 0});
if(l == r)
return ;
int mid = (l + r) >> 1;
build(X[k].lson, l, mid);
build(X[k].rson, mid + 1, r);
}
inline void solve(int u, int x1, int y1, int x2, int y2){
int now = get(L, R, L, R, x1, y1, x2, y2);
X[u].V.push_back({all, now});
}
inline void dfs(int k){
if(X[k].l == X[k].r)
return ;
int mid = (X[k].l + X[k].r) >> 1;
solve(X[k].lson, 1, X[k].l, mid, X[k].r - 1);
solve(X[k].rson, X[k].l + 1, mid + 1, X[k].r, n);
dfs(X[k].lson);
dfs(X[k].rson);
}
int main(){
// freopen("A.in", "r", stdin);
init();
n = read(), q = read(), k = read(), S = read();
build(rt, 1, n);
for(int i = 1; i <= q; ++i){
L = read(), R = read();
all = 1ll * (1ll * (R - L + 2) * (R - L + 1) >> 1) % mod * (S + 1) % mod;
mul = 1ll * mul * all % mod;
dfs(rt);
X[rt].V.push_back({all, L == 1 && R == n});
}
for(int i = 1; i <= k; ++i){
int mulS = 1;
for(int j = 0; j <= i + 1; ++j){
a[j] = (j ? add(a[j - 1], qpow(j, i)) : qpow(j, i));
mulS = 1ll * mulS * dec(S, j) % mod;
}
if(S <= i + 1)
F[i] = a[S];
else{
for(int j = 0; j <= i + 1; ++j){
if((i + 1 - j) & 1)
getdec(F[i], 1ll * a[j] * mulS % mod * qpow(dec(S, j), mod - 2) % mod * ifac[j] % mod * ifac[i + 1 - j] % mod);
else
getadd(F[i], 1ll * a[j] * mulS % mod * qpow(dec(S, j), mod - 2) % mod * ifac[j] % mod * ifac[i + 1 - j] % mod);
}
}
F[i] = 1ll * F[i] * ifac[i] % mod;
}
G[0] = 1;
for(int now = 1; now <= q; ++now){
for(int i = 0; i <= k; ++i){
if(!G[i])
continue;
for(int j = 0; i + j <= k; ++j)
getadd(H[i + j], 1ll * G[i] * F[j] % mod);
}
for(int i = 0; i <= k; ++i)
G[i] = H[i], H[i] = 0;
fk[now] = 1ll * fac[k] * G[k] % mod;
}
for(int u = 1; u <= cnt; ++u){
// cerr << "node: " << X[u].l << ' ' << X[u].r << '\n';
int ans = 0;
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i <= q; ++i){
// cerr << "w: " << X[u].V[i].fi << ' ' << X[u].V[i].se << '\n';
int now = i & 1, pre = now ^ 1;
dp[now][0] = 1ll * X[u].V[i].fi * dp[pre][0] % mod;
for(int j = 1; j <= i; ++j)
dp[now][j] = add(1ll * X[u].V[i].fi * dp[pre][j] % mod, 1ll * X[u].V[i].se * dp[pre][j - 1] % mod);
}
for(int i = 1; i <= q; ++i)
getadd(ans, 1ll * fk[i] * dp[q & 1][i] % mod);
// cerr << ans << '\n';
getadd(Ans, ans);
}
write(1ll * Ans * qpow(mul, mod - 2) % mod);
return 0;
}

浙公网安备 33010602011771号