闲话 22.10.19
闲话
听说写一些比较意识流的闲话会像闲话一点(
比方说多头
但是既然都开始写了那就无所谓像了
想啥就写啥吧
话说jjdw打字的手法实在是娴熟
每次看到都想吐槽来着
我还得多练(
话说回来
打KTT的时候一直又WA又T不知道为什么
然后贺了一个加号
然后A了
我不知道为什么
[今天要推的歌是Aster!]
话说下午我在哼安河桥
然后crs吐槽歌十分悲伤
然后我唱Aster 然后问crs为什么不吐槽了
然后crs表示歌很好听
我不是十分的理解
杂题
关于下面的一些讨论,EI 通过了四种方式证明了某个更强的结论
付公主有一个可爱的背包qwq
这个背包最多可以装 \(10^5\) 大小的东西
付公主有 \(n\) 种商品,她要准备出摊了
每种商品体积为 \(v_i\),都有无限件
给定 \(m\),对于 \(s\in [1,m]\),请你回答用这些商品恰好装 \(s\) 体积的方案数
\(n,m\le 10^5,v_i \le m\)
板子题。
首先这题用普通完全背包肯定是跑不动的。于是考虑一个多项式优化。
对于一个商品,我们可以把它拆成选 \(k\ (k >= 0)\) 种的可能性加和。
考察单项式相乘的情况:
可以看到,假设我们将可能性看做单项式的系数,背包容量看做单项式的指数,则两个单项式相乘就可以看做背包决策空间内两种决策的合并。推广到多项式,不难得到第 \(k\) 种商品的表示法:
第二个等号考虑 \(f_k(x) \times x^{v_k} + 1 = f_k(x)\) 。
于是我们只需要把所有多项式卷积起来,取答案的前 \(m\) 项系数就是答案。
但是如果直接卷复杂度就是 \(O(n^2 \log n)\) 的了。然后考虑优化。
设 \(G(x)\) 为答案的生成函数。立得
我们只需要求出分母,求个逆就是答案。
然后考虑分母:
第三步考虑一个 \(\ln(1-x^k)\) 的麦克劳林展开。
随后我们就可以通过用一个桶预处理第三个求和号,用 \(O(\sum_{i=1}^m \frac mi) = O(m \log m)\) 的时间得到需要的前 \((m+1)\) 项。
得到所有系数后做一次 \(\exp\) 做一次求逆即可得到答案。
code
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define rep(i, a, b) for (register int(i) = (a), i##_ = (b) + 1; (i) < i##_; ++(i))
#define pre(i, a, b) for (register int(i) = (a), i##_ = (b) - 1; (i) > i##_; --(i))
using namespace std;
const int N = 3e5 + 10, mod = 998244353, g = 3;
const int siz_int = sizeof(int);
#ifdef ONLINE_JUDGE
char buf[1<<21], *p1 = buf, *p2 = buf; inline char getc() { return (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1 == p2) ? EOF : *p1++); }
#define getchar getc
#endif
template <typename T> inline 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 (ch >= '0' and ch <= '9') x = (x<<1) + (x<<3) + (ch^48), ch = getchar(); f && (x = -x);
} template <typename T, typename ... Args> inline void get(T & x, Args & ... _Args) { get(x); get(_Args...); }
int n, m, len = 1, a[N], cnt[N], ifv[N];
typedef long long ll; typedef __int128 lll;
struct FastMod { int m; ll b; FastMod(int _m) { m = _m; b = ((lll)1<<64) / m; } int operator() (ll a) {ll q = ((lll)a * b) >> 64; a -= q * m; if (a >= m) a -= m; return a; } } Mod(mod);
int add(int a, int b) { return (a += b) >= mod ? a - mod : a; } template <typename ...Args> int add(int a, Args ...b) { return add(a, add(b...)); }
int mul(int a, int b) { return Mod(1ll * a * b); } template <typename ...Args> int mul(int a, Args ...b) { return mul(a, mul(b...)); }
int btrs[N << 1];
inline int initrs(int k) {
int limit = 1;
while (limit < k) limit <<= 1;
for (register int i = 0 ; i < limit; i ++) btrs[i] = (btrs[i >> 1] >> 1) | ((i & 1) ? limit >> 1 : 0);
return limit;
}
inline int qp(int a, int b) {
int ret = 1;
while (b) {
if (b & 1) ret = mul(ret, a);
a = mul(a, a);
b >>= 1;
} return ret;
} inline int inv(int a) { return qp(a, mod-2); }
const int invg = inv(g), inv2 = (mod + 1) >> 1;
const int L = 1 << 21;
int w[2][L];
int IUR() {
w[0][0] = w[1][0] = 1; int wn = qp(g, (mod-1) / L);
for (register int i = 1; i < L; i++) w[0][L - i] = w[1][i] = mul(w[1][i - 1], wn);
return 1;
} int dummy = IUR();
struct poly {
vector <int> f;
int operator [] (const int & pos) const { return f[pos]; }
int & operator [] (const int & pos) { return f[pos]; }
int deg() {return f.size(); }
int deg() const {return f.size(); }
void Set(int n) { f.resize(n); }
void Adjust() { while (f.size() > 1 and f.back() == 0) f.pop_back(); }
void Reverse() { reverse(f.begin(), f.end()); }
void scan(int n = -1) { if (n < 0) get(n); Set(n); for (register int i = 0; i < n; i++) get(f[i]); }
void print() { for (int x : f) printf("%d ", x); }
void getFac(int k) { Set(k); f[0] = 1; for (int i = 1; i <= k; i++) f[i] = mul(f[i - 1], i); }
void getInv(int k) { Set(k); f[0] = f[1] = 1; for (int i = 1; i <= k; ++ i) f[i] = mul(mod - mod / i, f[mod % i]); }
void deri() { for (register int i = 0; i + 1 < (int)f.size(); ++i) f[i] = mul(f[i+1], i+1); f.back() = 0; }
void intg() { for (register int i = f.size() - 1; i >= 1; --i) f[i] = mul(f[i-1], inv(i)); f[0] = 0; }
poly Deri() {
poly ret; ret.Set(deg());
for (int i = 0; i + 1 < deg(); ++i) {
ret[i] = mul(f[i+1], i+1);
} return ret;
} poly Intg() {
poly ret, inv; ret.Set(deg()), inv.getInv(deg() - 1);
for (int i = deg() - 1; i >= 1; --i) {
ret[i] = mul(f[i-1], inv[i]);
} return ret;
}
inline void NTT (const int lim, const int type) {
Set(lim);
for (register int i = 0; i < lim; i++) if (i < btrs[i]) swap(f[i], f[btrs[i]]);
for (register int mid = 1, x, y; mid < lim; mid <<= 1) {
for (register int i = L / (mid<<1), j = 0; j < lim; j += (mid << 1)) {
for (register int k = 0; k < mid; k++) {
x = f[j + k], y = mul(w[type][i * k], f[j + k + mid]);
f[j + k] = add(x, y);
f[j + k + mid] = add(x, mod - y);
}
}
} if (type == 1) return;
int inv = qp(lim, mod - 2);
for (register int i = 0; i < lim; i++) f[i] = mul(f[i], inv);
}
friend poly operator + (const poly & x, const poly & y) {
poly ret; ret.Set(max(x.deg(), y.deg()));
for (register int i = 0; i < x.deg(); ++i) ret[i] = x[i];
for (register int i = 0; i < y.deg(); ++i) ret[i] = add(ret[i], y[i]);
return ret;
} void operator += (const poly & x) {
Set(max(deg(), x.deg()));
for (register int i = 0; i < x.deg(); ++i) f[i] = add(f[i], x[i]);
}
friend poly operator - (const poly & x, const poly & y) {
poly ret; ret.Set(max(x.deg(), y.deg()));
for (register int i = 0; i < x.deg(); ++i) ret[i] = x[i];
for (register int i = 0; i < y.deg(); ++i) ret[i] = add(ret[i], mod - y[i]);
return ret;
} void operator -= (const poly & x) {
Set(max(deg(), x.deg()));
for (register int i = 0; i < x.deg(); ++i) f[i] = add(f[i], mod - x[i]);
}
friend poly operator * (const poly & x, const poly & y) {
poly ret, A = x, B = y;
int limit = initrs(A.deg() + B.deg() - 1);
A.NTT(limit, 1), B.NTT(limit, 1); ret.Set(limit);
for (register int i = 0; i < limit; i++) ret[i] = mul(A[i], B[i]);
ret.NTT(limit, 0); ret.Adjust();
return ret;
} void operator *= (const poly & x) {
poly A = x;
int limit = initrs(deg() + A.deg() - 1);
A.NTT(limit, 1); NTT(limit, 1);
for (register int i = 0; i < limit; i++) f[i] = mul(A[i], f[i]);
NTT(limit, 0); Adjust();
}
poly Inv() {
poly ret; ret.Set(1);
if (f.empty()) return ret;
ret[0] = inv(f[0]); poly A, B;
for (register int len = 2, limit; len < (deg() << 1); len <<= 1) {
A.f.assign((*this).f.begin(), (*this).f.begin() + min(len, deg()));
B = ret; B.Set(min(len, deg()));
limit = initrs(A.deg() + B.deg() - 1);
A.NTT(limit, 1); B.NTT(limit, 1);
ret.Set(limit);
for (register int i = 0; i < limit; i++) ret[i] = mul(add(2, mod - mul(A[i], B[i])), B[i]);
ret.NTT(limit, 0);
ret.Set(len);
} ret.Set(deg()); return ret;
}
poly Ln() {
poly ret = Deri(), Iv = Inv();
ret *= Iv; ret.intg(); ret.Set(deg());
return ret;
}
poly Exp() {
poly ret; ret.Set(1); ret[0] = 1;
poly A, B;
for (register int len = 2; len < (deg() << 1); len <<= 1) {
ret.Set(len); A = ret.Ln();
B.f.assign((*this).f.begin(), (*this).f.begin() + min(len, deg()));
B -= A; B[0]++; ret *= B;
ret.Set(len);
} ret.Set(deg()); return ret;
}
} F;
signed main() {
get(n, m);
rep(i,1,n) get(a[i]), cnt[a[i]]++;
while (len <= m) len <<= 1;
ifv[0] = ifv[1] = 1;
rep(i,2,len) ifv[i] = mul((mod - mod / i), ifv[mod % i]);
F.Set(len);
rep(i,1,m) if (cnt[i]) {
for (int j = 1; i * j < len; ++ j) {
F[i * j] = add(F[i * j], mul(cnt[i], (mod - ifv[j])));
}
}
F = F.Exp();
F = F.Inv();
rep(i,1,m) printf("%d\n", F[i]);
}
actually还做了一道题 P5175
但是太水了略去
但是想请各位卡卡常(
题面比较形式化,在此不放。
多项式题。
由经典dp结论,我们有 答案即为
讨论减号前后的两个部分。
首先是前面的:
\(n,k\) 其实是同阶的。直接算就完了。
然后是后面的:
\(B_i\) 是伯努利数。对多项式大佬来说显然不是什么问题
\(B_i\) 的EGF是 \(\frac x {e^x - 1}\)。
于是我们就能得到答案了。
懒得写码了(
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/chitchat221019.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。