数学做题笔记
P1829 [国家集训队] Crash 的数字表格:推式子。
本质上和 P3768 简单的数学题 没有多大区别,杜教筛筛一下 \(\phi\) 就能解决了。
顺带一提,P3768 最后推出来是 \(\sum\limits_{j=1}^nS(\left\lfloor\frac{n}{j}\right\rfloor)^2(j^2\phi(j))\)。(
\(\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m\text{lcm}(i,j)\)
\(=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\dfrac{ij}{\gcd(i,j)}\)
\(=\sum\limits_{d=1}^n\dfrac{1}{d}\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=d]\space ij\)
这里是一如既往的换掉 \(\text{lcm}\) 变成 \(\gcd\)
然后从 \(i,j\) 里面提出来 \(d^2\),显然不为 \(d\) 倍数时无贡献,那么变成
\(=\sum\limits_{d=1}^nd\sum\limits_{i=1}^{\frac{n}{d}}\sum\limits_{j=1}^{\frac{m}{d}}[\gcd(i,j)=1] \space ij\)
然后就可以开始莫反了,哈哈哈。
形式大约是 \(\sum\mu(i)g(i)\) 这样子推。
设 \(f(n,m)=\sum\limits_{i=1}^{\frac{n}{d}}\sum\limits_{j=1}^{\frac{m}{d}}[\gcd(i,j)=1] \space ij\),\(g(n)=\sum\limits_{d|n}f(d)\)
就能得到
\(g(d)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[d|\gcd(i,j)]\space ij\)
同理直接提 \(d^2\),得到
\(g(d)=d^2\sum\limits_{i=1}^{\frac{n}{d}}\sum\limits_{j=1}^{\frac{m}{d}}ij=d^2(\sum\limits_{i=1}^{\frac{n}{d}}i)(\sum\limits_{i=1}^{\frac{m}{d}}i)\)
代回去得到 \(res=\sum\limits_{d=1}^nd\sum\limits_{i=1}^{\frac{n}{d}}\mu(i)i^2(\sum\limits_{j=1}^{\frac{n}{id}}j)(\sum\limits_{j=1}^{\frac{m}{id}}j)\)
可以了,\(O(n)\) 做法到手。下面看一眼 借鉴了 Solution 的 根号复杂度做法。
事实上这个做法的思路只是将枚举因数变成了枚举 \(id\) 也就是乘积
然后把前缀和给提出来预处理就变得非常迅速
\(=\sum\limits_{j=1}^n(\sum\limits_{i=1}^{\frac{n}{j}}i)(\sum\limits_{i=1}^{\frac{m}{j}}i)\times j\sum\limits_{i|j}i\mu(i)\)
就可以愉快地 \(O(\sqrt n)\) 单次询问求解啦。
P1446 [HNOI2008] Cards:大致是给出三种牌数然后给一堆置换,求方案数。
Burnside 引理板题。直接套上去即可。
这个洗牌就是一个置换群,用类似求环的方法直接求出来置换的循环即可。
求出来之后直接 DP 求解方案数即可~
inline int qinyubo() {
int cnt = 0;
for (int i = sr; ~i; --i) for (int j = sb; ~j; --j)
for (int k = sg; ~k; --k) f[i][j][k] = 0;
for (int i = 1; i <= n; ++i) vis[i] = false;
for (int i = 1; i <= n; ++i) {
if (vis[i]) continue;
int cur = i, curans = 0;
while (!vis[cur])
++curans, vis[cur] = true, cur = to[cur];
siz[++cnt] = curans;
}
f[0][0][0] = 1;
for (int cur = 1; cur <= cnt; ++cur)
for (int i = sr; ~i; --i) for (int j = sb; ~j; --j)
for (int k = sg; ~k; --k) {
if (i >= siz[cur]) (f[i][j][k] += f[i-siz[cur]][j][k]) %= p;
if (j >= siz[cur]) (f[i][j][k] += f[i][j-siz[cur]][k]) %= p;
if (k >= siz[cur]) (f[i][j][k] += f[i][j][k-siz[cur]]) %= p;
}
return f[sr][sb][sg];
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> sr >> sb >> sg >> m >> p;
n = sr + sb + sg;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) cin >> to[j];
(res += qinyubo()) %= p;
}
for (int i = 1; i <= n; ++i) to[i] = i;
(res += qinyubo()) %= p;
(res *= qpow(m + 1, p - 2)) %= p;
cout << res << endl;
return 0;
}
P3197 [HNOI2008] 越狱:哈哈哈哈哈哈哈哈哈哈哈哈题。
考虑不发生越狱的方案数,第一个房间有 \(m\) 种,后面都是 \(m-1\) 种。
用总方案数减掉不合法数得出答案。
all = qpow(m, n), to = m * qpow(m - 1, n - 1) % md;
res = ((all - to) % md + md) % md;
cout << res << endl;
P4609 [FJOI2016] 建筑师:城市规划。
首先显然可以确定一个最高的建筑,以此为中心,分成左半和右半。
同时可以认为,左半分为了 \(A-1\) 个段,右半为 \(B-1\)。
然后可以将一个可以被看见的建筑理解为一个以其为开头的段。
那么这一段中以其为开头,其余的可以随便排序。
计算答案发现,假设某一段长度为 \(x\),则排列方案数为 \(P_{x-1}^{x-1}\)。
而一个大小为 \(x\) 的环,排列方案数也恰好为 \(\dfrac{P_x^x}{x}=P_{x-1}^{x-1}\)。
则可以理解为将 \(n-1\) 个元素分为 \(A+B-2\) 个环。
那么答案就是这样,左边右边分一下,一个组合数,然后分一下环,乘起来。
答案即为 \(S_1(n-1, A+B-1)\times\dbinom{A+B-2}{A-1}\)。
res
表示第一类斯特林数,c
表示组合数。
inline void init() {
res[0][0] = 1;
for (int j = 1; j <= 5e4; ++j)
for (int i = 1; i <= 2e2; ++i)
res[j][i] = (res[j-1][i-1] + (j - 1) * res[j-1][i]) % p;
for (int i = 0; i <= 2e2; ++i) c[0][i] = 1;
for (int i = 1; i <= 2e2; ++i)
for (int j = 1; j <= 2e2; ++j)
c[i][j] = (c[i-1][j-1] + c[i][j-1]) % p;
}
inline void query() {
cin >> n >> a >> b;
int ans = res[n-1][a+b-2] * c[a-1][a+b-2];
cout << ans % p << endl;
}
CF932E Team Work:推式子题。
\(\quad\sum\limits_{i=1}^n\binom{n}{i}\times i^k\)
\(=\sum\limits_{i=1}^n\binom{n}{i}\sum\limits_{j=0}^kS_2(k,j)\dfrac{(n+1)^{\underline{j+1}}}{j+1}\)
\(=\sum\limits_{i=1}^n\dfrac{n!}{i!\space (n-i)!}\sum\limits_{j=0}^kS_2(k,j)\)