2025-12-31~2026-1-2 hetao1733837 的刷题笔记

2025-12-31~2026-1-1 hetao1733837 的刷题笔记

2025-12-31

居然是 2025 年的最后一篇笔记了吗?可能不是,因为还有一堆草稿......

不过,还是祝自己新年快乐吧!2026 年一定要继续追梦哦!

LG1446 [HNOI2008] Cards

原题链接:[HNOI2008] Cards

分析

被骗了!《算法竞赛》这道题的结论是可以 H a c k Hack Hack 的!

那我看题解......

操,踏🐎的上了大半节课了,起床号才响,ZYZ 赢得相当彻底!

考虑一发 D P DP DP,更确切说是背包,设 f i , j , k f_{i,j,k} fi,j,k 表示三种颜色分别用了多少的方案数。

暴力转移就行了。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 65;
int fac[N], r, g, b, m, P, n;
int x[N], sz[N], f[N][N][N];
bool vis[N];
int qpow(int a, int b){
    int res = 1;
    while (b){
        if (b & 1) 
            res = res * a % P;
        a = a * a % P;
        b >>= 1;
    }
    return res;
}
void init(){
    fac[0] = 1;
    for (int i = 1; i < N; i++){
        fac[i] = fac[i - 1] * i % P;
    }
}
int calc(){
    for (int i = 0; i <= r; i++)
        for (int j = 0; j <= g; j++)
            for (int k = 0; k <= b; k++)
                f[i][j][k] = 0;
    memset(vis, 0, sizeof(vis));
    int tot = 0;
    for (int i = 1; i <= n; i++){
        if (!vis[i]){
            int p = i, len = 0;
            while (!vis[p]){
                len++;
                vis[p] = 1;
                p = x[p];
            }
            sz[++tot] = len;
        }
    }
    f[0][0][0] = 1;
    for (int idx = 1; idx <= tot; idx++){
        int len = sz[idx];
        for (int i = r; i >= 0; i--)
            for (int j = g; j >= 0; j--)
                for (int k = b; k >= 0; k--){
                    if (i >= len) 
                        f[i][j][k] = (f[i][j][k] + f[i - len][j][k]) % P;
                    if (j >= len) 
                        f[i][j][k] = (f[i][j][k] + f[i][j - len][k]) % P;
                    if (k >= len) 
                        f[i][j][k] = (f[i][j][k] + f[i][j][k - len]) % P;
                }
    }
    return f[r][g][b];
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> r >> g >> b >> m >> P;
    n = r + g + b;
    init();
    int ans = 0;
    for (int i = 1; i <= m; i++){
        for (int j = 1; j <= n; j++){
            cin >> x[j];
        }
        ans = (ans + calc()) % P;
    }
    for (int j = 1; j <= n; j++){
        x[j] = j;
    }
    ans = (ans + calc()) % P;
    int inv = qpow(m + 1, P - 2);
    cout << ans * inv % P;
}

这是啥啊!《算法竞赛》一直骗我!

2026-1-1

被卡了两年了。·

LG4980 【模板】Pólya 定理

原题链接:【模板】Pólya 定理

分析

Wishtoday,咋整上离散数学了?

我应该知道公式,然后就是一些小化简。

由 B u r n s i d e Burnside Burnside 引理, 定义 M = { 1 , ... , n } M=\{1,\dots,n\} M={1,...,n} 的可能初始排列,群 G G G 表示旋转 1 → n − 1 1\rightarrow n-1 1→n−1 次。则
a n s = 1 ∣ G ∣ ∑ g ∈ G M g ans=\frac{1}{|G|}\sum\limits_{g\in G}^{}{M^g} ans=∣G∣1g∈G∑Mg

由于在环上,存在一个 gcd ⁡ \gcd gcd,因而进一步化为
1 n ∑ k = 1 n n gcd ⁡ ( k , n ) \frac{1}{n}\sum\limits_{k=1}^{n}{n^{\gcd(k,n)}} n1k=1∑nngcd(k,n)

然后上莫比乌斯反演,呃,我并不会
1 n ∑ d ∣ n n d × ∑ k = 1 n d [ gcd ⁡ ( k , n d ) = = 1 ] \frac{1}{n}\sum\limits_{d|n}{n^d}\times\sum\limits_{k=1}^{\frac{n}{d}}{[\gcd(k,\frac{n}{d})==1]} n1d∣n∑nd×k=1∑dn[gcd(k,dn)==1]

发现后面是个欧拉函数,直接带入
1 n ∑ d ∣ n n d ϕ ( n d ) \frac{1}{n}\sum\limits_{d|n}{n^d\phi(\frac{n}{d})} n1d∣n∑ndϕ(dn)

求就行了......

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 1000000007
using namespace std; 
int T;
int n;
int qpow(int a, int b){
	int res = 1;
	while (b){
		if (b & 1)
			res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	} 
	return res;
}
int phi(int x){
	int res = x;
	for (int i = 2; i <= sqrt(x); i++){
		if (x % i != 0)
			continue;
		res = res - res / i;
		while (x % i == 0)
			x /= i;
	}
	if (x != 1)
		res = res - res / x;
	return res;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> T;
	while (T--){
		cin >> n;
		int k = sqrt(n);
		int ans = 0;
		for (int i = 1; i <= k; i++){
			if (n % i != 0)
				continue;
			int tmp1 = phi(i);
			int tmp2 = qpow(n, n / i);
			tmp2 = tmp2 * tmp1 % mod;
			ans = (ans + tmp2) % mod;
			if (i * i != n){
				int tmp3 = phi(n / i);
				int tmp4 = qpow(n, i);
				tmp4 = tmp4 * tmp3 % mod;
				ans = (ans + tmp4) % mod; 
			}
		}
		cout << ans * qpow(n, mod - 2) % mod << '\n';
	}
}

我找 DeepSeek 再学一下这个东西吧......

2026-1-2

LG2561 [AHOI2002] 黑白瓷砖

原题链接:[AHOI2002] 黑白瓷砖

分析

看了一眼题,觉得可能是拆成一个项链之类的吧......我看看题解吧......

没看懂......

留给明天,先打板子!

板子打完了......还是太抽象了......

稍微懂了一点吧......

就是说,之前那个拆开的是错的,我们直接去考虑题目中给出的神秘三角形,然后会发现有 6 种变化,即不动、旋转×2,翻转×3,手推一发,得出式子
a n s = 1 6 ( 2 N + 2 × 2 ⌈ N 3 ⌉ + 3 × 2 ( N − ⌈ N 2 ⌉ 2 + ⌈ N 2 ⌉ ) ) N = n × ( n + 1 ) 2 ans=\frac{1}{6}(2^N+2\times 2^{\left\lceil\frac{N}{3}\right\rceil}+3\times 2^{(\frac{N-\left\lceil\frac{N}{2}\right\rceil}{2}+\left\lceil\frac{N}{2}\right\rceil)})\\ N=\frac{n\times(n+1)}{2} ans=61(2N+2×2⌈3N⌉+3×2(2N−⌈2N⌉+⌈2N⌉))N=2n×(n+1)

居然要高精度!我*****

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int BS = 10000;
const int N = 205;
int n;
struct node{
    int num[N], len;
    node() : len(){
        memset(num, 0, sizeof(num));
    }
    int& operator[](int x){
        return num[x];
    }
    const int& operator[](int const &x) const{
        return num[x];
    }
    void print(void){
        printf("%d", num[len - 1]);
        for (int i = len - 2; ~i; i--)
            printf("%04d", num[i]); 
    }
};
node operator+(node x, node y){
    node res;
    if (x.len < y.len)
        swap(x, y);
    res[0] = 0; 
    for (res.len = 0; res.len < x.len || res[res.len]; res.len++){
        res[res.len] += x[res.len] + y[res.len];
        if (res[res.len] > BS){
            res[res.len + 1] = 1; 
            res[res.len] -= BS;
        }
        else{
            res[res.len + 1] = 0; 
        }
    }
    return res;
}
node operator*(node x, int y){
    node res;
    res[0] = 0; 
    for (res.len = 0; res.len < x.len || res[res.len]; res.len++){
        res[res.len] += x[res.len] * y;
        if (res[res.len] >= BS){
            res[res.len + 1] = res[res.len] / BS; 
            res[res.len] %= BS;
        }
        else{
            res[res.len + 1] = 0;
        }
    }
    while (res.len > 0 && res[res.len - 1] == 0)
        res.len--;
    return res;
}
node operator/(node x, int y){
    for (int i = x.len - 1; ~i; i--){
        if (i)
            x[i - 1] += (x[i] % y) * BS;
        x[i] /= y; 
    }
    while (x.len && !x[x.len - 1])
        x.len--;
    return x;
}
node a, b, c, ans;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    int aa = n * (n + 1) / 2;
    int bb = (aa - (n + 1) / 2) / 2 + (n + 1) / 2;
    int cc = (aa + 2) / 3;
    a[0] = 1;
    a.len = 1;
    for (int i = 1; i <= aa; i++){
        a = a * 2;
    }
    b[0] = 1;
    b.len = 1;
    for (int i = 1; i <= bb; i++){
        b = b * 2;
    }
    b = b * 3;
    c[0] = 1;
    c.len = 1;
    for (int i = 1; i <= cc; i++){
        c = c * 2;
    }
    c = c * 2;
    ans = (a + b + c) / 6;
    ans.print();
}

LG10031 「Cfz Round 3」Xor with Gcd

原题链接:「Cfz Round 3」Xor with Gcd

分析

对于每个 n n n 的因数 d d d,满足 gcd ⁡ ( i , n ) = d \gcd(i,n)=d gcd(i,n)=d 的 i i i 的个数为 ϕ ( n d ) \phi(\frac{n}{d}) ϕ(dn)。

当 ϕ ( n d ) \phi(\frac{n}{d}) ϕ(dn) 为偶数的时候,不会对答案产生贡献。

使得 ϕ ( x ) \phi(x) ϕ(x) 为奇数,当且仅当 x = 1 x=1 x=1 或 x = 2 x=2 x=2。

故,当 n n n 为奇数时,答案为 n n n;当 n n n 为偶数时,答案为 n ⊕ n 2 n\oplus \frac{n}{2} n⊕2n。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int T;
int n;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> T;
    while (T--){
        cin >> n;
        if (n % 2 == 0)
            cout << (n ^ (n / 2ll)) << '\n';
        else
            cout << n << '\n';
    }
}

累了,想睡会......

发了吧,一会再打几道简单题睡觉!

相关推荐
jimmyleeee2 小时前
人工智能基础知识笔记三十一:Langfuse
人工智能·笔记
争不过朝夕,又念着往昔2 小时前
C++AI
开发语言·c++·人工智能
敲上瘾2 小时前
C++11线程库指南:线程、锁、原子操作与并发编程实战
开发语言·c++·多线程
laplace01232 小时前
Part 4. LangChain 1.0 Agent 开发流程(Markdown 笔记)
前端·javascript·笔记·python·语言模型·langchain
Aliex_git2 小时前
性能优化 - 渲染优化
前端·javascript·笔记·学习·性能优化·html
yyy(十一月限定版)2 小时前
算法——差分
算法
yyy(十一月限定版)2 小时前
算法——模拟
算法
DeepVis Research2 小时前
【Chaos/Neuro】2026年度混沌动力学仿真与机器遗忘算法基准索引 (Benchmark Index)
人工智能·算法·数据集·混沌工程·高性能计算
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs]pidfs
linux·笔记·学习