闲话 22.11.7

闲话

行吧我昨天闲话时间写错了
今天没有(

所以为什么模拟赛T1是黑题啊
所以为什么黄题 我加暴力会挂掉删掉就切了啊
我不理解

突然发现 Longge 的问题 我还没写
因此我数学很差

[这里应该放一张圆神的图 但是我没找到]
[所以先咕着 大家可以从评论区发(]

杂题

ABC162E
加强版 loj6491

给定\(n,k\),求

\[\sum^k_{a_1=1}\sum^k_{a_2=1}\sum^k_{a_3=1}\dots\sum^k_{a_n=1}\gcd(a_1,a_2,a_3,\dots,a_n)\bmod\ 1000000007 \]

\(n,k \le 10^{11}\)

昨天看到 2神 在写这题的题解
然后写了一下
同时也想写不用动脑子的题了

然后直接化式子:

\[\begin{aligned} & \sum^k_{a_1=1}\sum^k_{a_2=1}\sum^k_{a_3=1}\dots\sum^k_{a_n=1}\gcd(a_1,a_2,a_3,\dots,a_n) \\ = & \ \sum^k_{a_1=1}\sum^k_{a_2=1}\sum^k_{a_3=1}\dots\sum^k_{a_n=1}\sum_{x=1}x[\gcd(a_1,a_2,a_3,\dots,a_n) = x] \\ = & \ \sum_{x=1}x\sum^{\lfloor\frac kx\rfloor}_{a_1=1}\sum^{\lfloor\frac kx\rfloor}_{a_2=1}\sum^{\lfloor\frac kx\rfloor}_{a_3=1}\dots\sum^{\lfloor\frac kx\rfloor}_{a_n=1}[\gcd(a_1,a_2,a_3,\dots,a_n) = 1] \\ = & \ \sum_{x=1}x\sum^{\lfloor\frac kx\rfloor}_{a_1=1}\sum^{\lfloor\frac kx\rfloor}_{a_2=1}\sum^{\lfloor\frac kx\rfloor}_{a_3=1}\dots\sum^{\lfloor\frac kx\rfloor}_{a_n=1}[\gcd(a_1,a_2,a_3,\dots,a_n) = 1] \\ = & \ \sum_{x=1}x\sum^{\lfloor\frac kx\rfloor}_{a_1=1}\sum^{\lfloor\frac kx\rfloor}_{a_2=1}\sum^{\lfloor\frac kx\rfloor}_{a_3=1}\dots\sum^{\lfloor\frac kx\rfloor}_{a_n=1}\sum_{d|\gcd(a_1,a_2,a_3,\dots,a_n)}\mu(d) \\ = & \ \sum_{x=1}x\sum_{d=1}\mu(d)\sum^{\lfloor\frac k{xd}\rfloor}_{a_1=1}\sum^{\lfloor\frac k{xd}\rfloor}_{a_2=1}\sum^{\lfloor\frac k{xd}\rfloor}_{a_3=1}\dots\sum^{\lfloor\frac k{xd}\rfloor}_{a_n=1} \\ = & \ \sum_{T=1}\sum_{d|T}\frac Td\mu(d)\sum^{\lfloor\frac k{T}\rfloor}_{a_1=1}\sum^{\lfloor\frac k{T}\rfloor}_{a_2=1}\sum^{\lfloor\frac k{T}\rfloor}_{a_3=1}\dots\sum^{\lfloor\frac k{T}\rfloor}_{a_n=1} \\ = & \ \sum_{T=1}\sum_{d|T}\frac Td\mu(d)\left\lfloor\frac kT\right\rfloor^n \\ = & \ \sum_{T=1}\left\lfloor\frac kT\right\rfloor^n\sum_{d|T}\frac Td\mu(d) \\ = & \ \sum_{T=1}\left\lfloor\frac kT\right\rfloor^n\varphi(T) \end{aligned}\]

一点脑子不用动的线性筛写法
#include <bits/stdc++.h>
using namespace std; 
template<typename T> void get(T & x) {
	x = 0; char ch = getchar(); bool f = false; while (ch < '0' or ch > '9') f = f or ch == '-', ch = getchar();
	while ('0' <= ch and ch <= '9') x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); f && (x = -x); 
} template <typename T, typename ... Args> void get(T & a, Args & ... b) { get(a); get(b...); }
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, k, ans;

int qp(int a, int b) {
	int ret = 1;
	while (b) {
		if (b & 1) ret = 1ll * ret * a % mod;
		a = 1ll * a * a % mod;
		b >>= 1;
	} return ret;
}

int prime[N], cnt, phi[N];
void sieve() {
	phi[1] = 1;
	rep(i,2,k) {
		if (phi[i] == 0) phi[i] = i - 1, prime[++cnt] = i;
		rep(j,1,cnt) {
			int t = i * prime[j];
			if (t > k) break;
			if (i % prime[j]) phi[t] = phi[i] * phi[prime[j]];
			else {
				phi[t] = phi[i] * prime[j];
				break;
			}
		}
	} rep(i,2,k) phi[i] = (phi[i] + phi[i - 1]) % mod;
}

signed main() {
	get(n, k);
	sieve();
	for (int l = 1, r; l <= k; l = r + 1) {
		r = k / (k / l);
		ans = (ans + 1ll * (phi[r] - phi[l - 1] + mod) * qp(k / l, n)) % mod;
	} cout << ans << '\n';
}
完全没有动脑子只是凭肌肉记忆打出来的杜
#include <bits/stdc++.h>
using namespace std; 
#define int unsigned long long
template<typename T> void get(T & x) {
	x = 0; char ch = getchar(); bool f = false; while (ch < '0' or ch > '9') f = f or ch == '-', ch = getchar();
	while ('0' <= ch and ch <= '9') x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); f && (x = -x); 
} template <typename T, typename ... Args> void get(T & a, Args & ... b) { get(a); get(b...); }
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
const int N = 3e7 + 10;
int n, k, ans, mx;

int qp(int a, int b) {
	int ret = 1;
	while (b) {
		if (b & 1) ret = ret * a;
		a = a * a;
		b >>= 1;
	} return ret;
}

int prime[N], cnt, phi[N];
void sieve(int k = N - 10) {
	phi[1] = 1;
	rep(i,2,k) {
		if (phi[i] == 0) phi[i] = i - 1, prime[++cnt] = i;
		rep(j,1,cnt) {
			int t = i * prime[j];
			if (t > k) break;
			if (i % prime[j]) phi[t] = phi[i] * phi[prime[j]];
			else {
				phi[t] = phi[i] * prime[j];
				break;
			}
		}
	} rep(i,2,k) phi[i] += phi[i - 1];
}

unordered_map <int,int> mp;
int cphi(int n) {
	if (n <= mx) return phi[n];
	if (mp.count(n)) return mp[n];
	int ret;
	if (n & 1) ret = ((n + 1) >> 1) * n;
	else ret = (n >> 1) * (n + 1);
	for (int l = 2, r; l <= n; l = r + 1) {
		r = n / (n / l);
		ret -= (r - l + 1) * cphi(n / l);
	} return mp[n] = ret;
}

signed main() {
	get(n, k); mx = pow(k, 2.0 / 3);
	sieve(mx);
	for (int l = 1, r; l <= k; l = r + 1) {
		r = k / (k / l);
		ans += 1ll * (cphi(r) - cphi(l - 1)) * qp(k / l, n);
	} cout << ans << '\n';
}



CF438E

我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树。 考虑一个含有 \(n\) 个互异正整数的序列 \(c_1,c_2\cdots,c_n\)。如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合 \(S = \{c_1,c_2,\cdots,c_n\}\) 中,我们的小朋友就会将其称作神犇的。

并且他认为,一棵带点权的树的权值,是其所有顶点权值的总和。

给出一个整数 \(m\),你能对于任意的 \(1\leq s\leq m\) 计算出权值为 \(s\) 的神犇二叉树的个数吗?请参照样例以更好的理解什么样的两棵二叉树会被视为不同的。 我们只需要知道答案关于 \(998244353\) 取模后的值。

输入第一行有 \(2\) 个整数 \(n,m\) \((1\leq n,m\leq 10^5)\)。 第二行有 \(n\) 个用空格隔开的互异的整数 \(c_1,c_2\cdots,c_n\) \((1\le c_i\le10^5)\)

输出 \(m\) 行,每行有一个整数。第 \(i\) 行应当含有权值恰为 \(i\) 的神犇二叉树的总数。请输出答案关于 \(998244353\) 取模的结果。

是 vfk 出的题(

\(f_i\)\(i\) 个节点的答案二叉树的个数。容易发现

\[f_n = \sum_{i=1}^n [i\in S] \sum_{j=1}^{n-i} f_{j}f_{n-i-j} \]

考虑用 \(F\) 生成 \(f\)。设 \(G\)\([i\in S]\) 的生成函数,我们对上式两边求和得到

\[F = F^2\times G + 1 \]

由于上式均为卷积形式,生成函数可以直接写出。
转换形式写作

\[G\times F^2 + F -1 = 0 \]

\[F = \frac{1 \pm\sqrt{1-4G}}{2G} \]

讨论可得取 \(+\) 不取 \(-\)。简化得到

\[F = \frac 2{1 + \sqrt{1 - 4G}} \]

套模板即可。

code

多项式部分采用重载了可与整型进行运算的poly

#include <bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
const int N = 1e5 + 10;
int n, m, b, mx;
unsigned a[N];

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n >> m; mx = max(mx, m + 1);
	rep(i,1,n) cin >> b, mx = max(mx, b), a[b] = 1;
	poly f(a, a+mx+1);
	f = 2 * (1 + (1 - 4 * f).pow((mod + 1) >> 1)).inv();
	rep(i,1,m) cout << f[i] << '\n';
}



CF838D

一架飞机有 \(n\) 个座位排成一列,有 \(m\) 名乘客依次上飞机。

乘客会选择一个目标座位(两人可以选同一个目标座位),然后选择从前门或者后门上飞机,上飞机后,他们会走到自己的目标座位,如果目标座位已经有人坐了,他们会继续往前走,在走到第一个空位后坐下。如果走到最后还没有找到座位,这名乘客就会生气。

问有多少种登机方案能让所有乘客都不生气。两个登机方案不同当且仅当第 \(i\) 位乘客的目标座位或上飞机走的门不同。

\(1\le m\le n\le 10^{18}\).

好题。

考虑走到最后这个条件不好表示,转化成另一种找座位。
我们将飞机转化成一个 \(n+1\) 个座位顺次分布的环,其中第 \(0\) 个座位表示走到最后找到的座位。
转化后我们需要安排乘客从任意位置开始行走,一直走到一个没有人坐的座位为止,在那里坐下。状态合法当且仅当 \(0\) 座位没人坐。

首先我们有所有情况为 \((2(n + 1))^m\),显然两种找法是等价的,因此每个人就可以从 \(n+1\) 个位置以两个方向出发,每个人的总可能性是 \(2(n+1)\)
然后计数合法情况。我们发现,最终状态两两可能性相同。因此不妨采用概率手段刻画情况:总共有 \(n+1\) 个座位,其中第 \(0\) 个座位被占的可能性是 \(\frac 1{n+1}\) 。总共占了 \(m\) 个座位,因此第 \(0\) 个座位被占的可能性为 \(m\times \frac 1{n+1}\),因此最终随意选出一个状态,是合法状态的可能性为 \(\frac {n+1-m}{n+1}\)

因此答案即为 \(\frac{n+1-m}{n+1}(2(n + 1))^m\)

code
#include <bits/stdc++.h>
using namespace std; 
template<typename T> void get(T & x) {
	x = 0; char ch = getchar(); bool f = false; while (ch < '0' or ch > '9') f = f or ch == '-', ch = getchar();
	while ('0' <= ch and ch <= '9') x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); f && (x = -x); 
} template <typename T, typename ... Args> void get(T & a, Args & ... b) { get(a); get(b...); }
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, m;

int qp(int a, int b) {
	int ret = 1;
	while (b) {
		if (b & 1) ret = 1ll * ret * a % mod;
		a = 1ll * a * a % mod;
		b >>= 1;
	} return ret;
}

signed main() {
	get(n, m);
	cout << 1ll * (n + 1 - m) * qp(n + 1, mod - 2) % mod * qp(2 * (n + 1), m) % mod;
}
posted @ 2022-11-07 19:40  joke3579  阅读(90)  评论(4编辑  收藏  举报