2026-01-21~22 hetao1733837 的刷题笔记

2026-01-21~22 hetao1733837 的刷题笔记

01-21

LGP10441 [JOIST 2024] 乒乓球 / Table Tennis

原题链接:[JOIST 2024] 乒乓球 / Table Tennis

分析

刚才在机房说话声音有点大啊......呃......好像有点康了......bur,自己一个人在机房待习惯了......有点愧疚......

我会 O ( 2 n ( n + 1 ) 2 × n 3 ) O(2^\frac{n(n+1)}{2}\times n^3) O(22n(n+1)×n3) 做法💀

一个有向图,是不是只会产生 C n 3 C_{n}^{3} Cn3 个三元环?而三元环只可能有两种情况,如图:

而右边的情况是当且仅当有一条边向外连了两条出边。即对于点集 ( i , j , k ) (i,j,k) (i,j,k),若 i → j i\rightarrow j i→j 且 i → k i\rightarrow k i→k,则 ( i , j , k ) (i,j,k) (i,j,k) 不成三元环。

呃......我是不是可以向题解思路靠近?

哦,就是一个结论:竞赛图三元环数量只与每个点的入度序列有关

对于一张完全没有三元环的图,其入度序列必定是 { 0 , 1 , 2 , ... , n − 1 } \{0,1,2,\dots,n-1\} {0,1,2,...,n−1}。

如果我们做一些小操作,比如有一段入度为 { x , x + 1 , x + 2 } \{x,x+1,x+2\} {x,x+1,x+2},将其变成 { x + 1 , x + 1 , x + 1 } \{x+1,x+1,x+1\} {x+1,x+1,x+1} 就会产生一个三元环,那似乎构造就可以了。

至于操作,找到一个三元环数量为 m m m 的最小图......就是这个东西,然后把图补全。那个最小的图就是一个组合数,嗯......

怎么写的有点像 lym 前几天给我发的语音。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5005;
int q, n, m, d[N], ans[N][N];
int calc(int x){
	int tmp = x * ((x - 1) / 2) * (x / 2);
	return (tmp - x * (x - 1) * (x - 2) / 6) / 2;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> q;
	while (q--){
		cin >> n >> m;
		if (m > calc(n)){
			cout << "No" << '\n';
			continue;
		}
		cout << "Yes" << '\n';
		for (int i = 1; i <= n; i++){
			d[i] = i - 1;
		}
		for (int i = 1; i <= n; i++){
			if (m <= calc(i)){
				m = calc(i) - m;
				if (i % 2 == 1){
					for (int j = 1; j <= i; j++){
						d[j] = (i - 1) / 2;
					}
				}
				else{
					for (int j = 1; j <= i; j++){
						d[j] = i / 2 - (j <= i / 2);
					}
				}
				while (m){
					for (int l = 1, r = 1; r < n; l = r + 1){
						r = l;
						while (r < i && d[r + 1] == d[r])
							r++;
						int tmp = r;
						while (m > 0 && l < r){
							m--;
							d[l++]--;
							d[r--]++;
						}
						r = tmp;
					}
				}
				break;
			}
		}
		sort(d + 1, d + n + 1);
		for (int i = 1; i <= n; i++){
			for (int j = 1; j <= n; j++){
				ans[i][j] = 0;
			}
		}
		for (int i = n; i >= 2; i--){
			d[i] = i - 1 - d[i];
			int l = i - 1, r = i - 1;
			while (true){
				l = r;
				while (l > 1 && d[l] == d[l - 1])
					l--;
				for (int j = l; j <= r; j++){
					if (d[i] > 0){
						d[i]--;
						d[j]--;
						ans[j][i] = 1;
					}
					else{
						ans[i][j] = 1;
					}
				}
				if (l == 1)
					break;
				r = l - 1;
			}
		}
		for (int i = 2; i <= n; i++){
			for (int j = 1; j < i; j++){
				cout << ans[i][j];
			}
			cout << '\n';
		}
	}
}

没懂......

感觉那个

cpp 复制代码
int calc(int x){
	int tmp = x * ((x - 1) / 2) * (x / 2);
	return (tmp - x * (x - 1) * (x - 2) / 6) / 2;
}

很类似 hxf 容斥吧......细节的话......我也不会证明。

我再想想......

相当于说......一张有 x x x 个点的图,最多含有的三元环个数是
x × x − 1 2 × x 2 − x × ( x − 1 ) × ( x − 2 ) 6 2 \frac{x\times\frac{x-1}{2}\times\frac{x}{2}-\frac{x\times (x-1)\times(x-2)}{6}}{2} 2x×2x−1×2x−6x×(x−1)×(x−2)

啥?其中 C x 3 = x × ( x − 1 ) × ( x − 2 ) 6 C_x^3=\frac{x\times (x-1)\times(x-2)}{6} Cx3=6x×(x−1)×(x−2)。那个分母上的 2 是反过来的两种图吧......

也就是说, x × x − 1 2 × x 2 x\times\frac{x-1}{2}\times\frac{x}{2} x×2x−1×2x 是所有图的情况?不见得完全吧......

为啥没人来机房啊?马上上课了,咋还没人来?
C x x − 2 = x × x − 1 2 C_x^{x-2}=x\times\frac{x-1}{2} Cxx−2=x×2x−1,那那个 x 2 \frac{x}{2} 2x 是啥?

就是,我从所有x个点里挑出来两个,然后不管他是从谁到谁,然后再挑一个,这个控制一下方向,减去所有......怎么说,就是不合法?然后我们之前不是不管那个方向吗?再除个2,好像是这样的。

并非这样吧......

理论上这个做法假完了!所以,看 aoao 的!

原作者给出了一些解释......

其实我没看懂......留到下辈子吧......

01-20

晚上居然还要考物理......发现 BO 想拿省一也不容易,进队也很难......所以,一方面来说要加倍努力,另一方面是做好心理准备......而且发现了吗?大幅提升实力,OI 就是现在,BO 也是现在。OI 是因为暑假基本没啥空余时间了,BO 是因为下学期一来基本就是停课,很难啊......OI 时间也会受影响。两个竞赛冲队重心都在高二,但是,我真的还有时间吗?如果想要更高的荣誉,那么,所要经受的一定更多。上天把我送到了双竞,一定有他的道理,我必须去完成他!

LGP5239 回忆京都

原题链接:回忆京都

分析

式子这么简单?卧槽,你从杨辉三角的角度理解是对的!

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 19260817
using namespace std;
const int N = 1005;
int q, n, m;
int sum[N][N];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> q;
    for (int i = 1; i < N; i++){
        for (int j = 1; j < N; j++){
            sum[i][j] = (sum[i - 1][j - 1] + sum[i - 1][j] + i) % mod;
        }
    }
    for (int cs = 1; cs <= q; cs++){
        cin >> n >> m;
        cout << sum[m][n] << '\n';
    }
}

LGP2606 [ZJOI2010] 排列计数

原题链接:[ZJOI2010] 排列计数

分析

这个 hxf 容斥似乎不太行,因为显然 ∀ \forall ∀ 好做一点。咦, m m m 是质数,需要 Lucas ⁡ \operatorname{Lucas} Lucas 定理。

咋推式子啊😫

巧妙地转换!把 ⌊ i 2 ⌋ \lfloor\frac{i}{2}\rfloor ⌊2i⌋ 转化为小根堆

那么,设 f i f_i fi 表示前 i i i 个不同的数,满足小根堆性质的排列数。

那么,讨论左右子树即可,确定左子树合法方案数 l l l,右子树 r r r。得出转移方程 f i = C i − 1 l × f l × f r f_i=C_{i-1}^{l}\times f_l\times f_r fi=Ci−1l×fl×fr。

拿一个 Lucas ⁡ \operatorname{Lucas} Lucas 定理没了。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000005;
int n, m;
int fac[N], inv[N], f[N];
int lg[N];
int qpow(int a, int b){
	int res = 1;
	while (b){
		if (b & 1)
			res = res * a % m;
		b >>= 1;
		a = a * a % m;
	}
	return res;
}
int C(int a, int b){
	if (b == 0)
		return 1;
	int c = C(a / m, b / m);
	int d = a % m;
	int e = b % m;
	int x;
	if (d < e)
		x = 0;
	else
		x = fac[d] * inv[e] % m * inv[d - e] % m;
	return c * x % m;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	fac[0] = 1;
    lg[0] = -1;
	for (int i = 1; i < N; i++){
		fac[i] = fac[i - 1] * i % m;
		lg[i] = lg[i >> 1] + 1;
	}
	int tmp = min(m - 1, n);
	inv[tmp] = qpow(fac[tmp], m - 2);
	for (int i = tmp - 1; i >= 0; i--){
		inv[i] = inv[i + 1] * (i + 1) % m;
	}
	f[1] = f[2] = 1;
	f[3] = 2;
	int l = 1, r = 1;
	for (int i = 4; i <= n; i++){
		if (i - (1 << lg[i]) + 1 <= (1 << lg[i] - 1))
			l++;
		else
			r++;
		f[i] = C(i - 1, l) * f[l] % m * f[r] % m;
	}
	cout << f[n];
}
相关推荐
承渊政道1 小时前
C++学习之旅【C++Vector类介绍—入门指南与核心概念解析】
c语言·开发语言·c++·学习·visual studio
四谎真好看1 小时前
JavaWeb学习笔记(Day05)之请求响应
笔记·学习·学习笔记·javaweb
Hcoco_me2 小时前
大模型面试题91:合并访存是什么?原理是什么?
人工智能·深度学习·算法·机器学习·vllm
2501_901147832 小时前
零钱兑换——动态规划与高性能优化学习笔记
学习·算法·面试·职场和发展·性能优化·动态规划·求职招聘
头发还没掉光光3 小时前
Linux网络之IP协议
linux·运维·网络·c++·tcp/ip
狐573 小时前
2026-01-22-LeetCode刷题笔记-3507-移除最小数对使数组有序I
笔记·leetcode
充值修改昵称3 小时前
数据结构基础:B树磁盘IO优化的数据结构艺术
数据结构·b树·python·算法
燃于AC之乐4 小时前
深入解剖STL Vector:从底层原理到核心接口的灵活运用
开发语言·c++·迭代器·stl·vector·源码分析·底层原理
程序员-King.10 小时前
day158—回溯—全排列(LeetCode-46)
算法·leetcode·深度优先·回溯·递归