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\) 级祖先。

sol for T5

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\) 次方的和。

sol T6 (1)
sol T6 (2)
sol T6 (3)

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;
}
posted @ 2026-07-10 15:51  nick_zha  阅读(13)  评论(0)    收藏  举报