[CF755G] PolandBall and Many Other Balls 题解
[CF755G] PolandBall and Many Other Balls 题解
题意概括
有一排 个球,定义一个组可以只包含一个球或者包含两个相邻的球。现在一个球只能分到一个组中,求从这些球中取出 组的方案数。
,。
题目分析
容易想到 转移:设 表示考虑前 个球,取了 组的方案数,那么有转移 ,暴力转移 。可以考虑多项式去优化,即令 ,则有:
这个式子显然可以构造其母函数,令 ,那么就有:
然后就是套路地解这个生成函数即可,设:
然后解方程组:
所以说:
然后就得到了 的每一项的系数,也即 的通项公式:
由于 的常数项为 ,所以说 的 到 项系数均为 ,所以说式子可以进一步化简,变得十分优美 :
多项式快速幂就能解决(并且快速幂过程常数项一直为 ,非常好写) ,下面附上代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 30;
const int M = 3e5;
const int mod = 998244353;
const int pr = 3;
const int ig = 332748118;
inline int add(int x, int y) {
x += y;
return x >= mod ? x - mod : x;
}
inline int del(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
int qpow(int a, int b) {
int res = 1;
while(b) {
if(b & 1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return res;
}
struct node {
int n, mx = 1, f[N], g[N];
void NTT(int *a, int len) {
int x, y, g, pw;
for(int j = len >> 1; j >= 1; j >>= 1) {
g = qpow(pr, (mod - 1) / (j << 1));
for(int i = 0; i < len; i += (j << 1)) {
pw = 1;
for(int k = 0; k < j; ++k, pw = 1ll * pw * g % mod) {
x = a[i + k]; y = a[i + j + k];
a[i + k] = add(x, y);
a[i + j + k] = 1ll * pw * del(x, y) % mod;
}
}
}
}
void INTT(int *a, int len) {
int x, y, g, pw;
for(int j = 1; j < len; j <<= 1) {
g = qpow(ig, (mod - 1) / (j << 1));
for(int i = 0; i < len; i += (j << 1)) {
pw = 1;
for(int k = 0; k < j; ++k, pw = 1ll * pw * g % mod) {
x = a[i + k]; y = 1ll * pw * a[i + j + k] % mod;
a[i + k] = add(x, y);
a[i + j + k] = del(x, y);
}
}
}
int Inv = qpow(len, mod - 2);
for(int i = 0; i < len; ++i) a[i] = 1ll * a[i] * Inv % mod;
}
void mul(int *a, int *b, int len) {
NTT(a, len); NTT(b, len);
for(int i = 0; i < len; ++i) a[i] = 1ll * a[i] * b[i] % mod;
INTT(a, len);
}
void INV(int *a, int *b, int len) {
static int A[N], B[N];
for(int i = 0; i < len; ++i) A[i] = a[i], a[i] = 0;
for(int i = 0; i < len; ++i) B[i] = b[i], b[i] = 0;
B[0] = qpow(A[0], mod - 2);
for(int j = 2; j < len; j <<= 1) {
for(int i = 0; i < (j << 1); ++i) a[i] = b[i] = 0;
for(int i = 0; i < j; ++i) a[i] = A[i];
for(int i = 0; i < (j >> 1); ++i) b[i] = B[i];
mul(a, b, j << 1);
for(int i = j; i < (j << 1); ++i) a[i] = 0;
for(int i = 0; i < j; ++i) a[i] = (mod - a[i]) % mod;
a[0] = add(a[0], 2);
NTT(a, j << 1);
for(int i = 0; i < (j << 1); ++i) a[i] = 1ll * a[i] * b[i] % mod;
INTT(a, j << 1);
for(int i = 0; i < j; ++i) B[i] = a[i];
}
for(int i = 0; i < len; ++i) a[i] = A[i], A[i] = 0;
for(int i = 0; i < len; ++i) b[i] = B[i], B[i] = 0;
}
void LN(int *a, int *b, int len) {
static int A[N], B[N];
for(int i = 0; i < len; ++i) A[i] = a[i], a[i] = 0;
for(int i = 0; i < len; ++i) B[i] = b[i], b[i] = 0;
INV(A, B, len);
for(int i = 0; i < len; ++i) b[i] = B[i];
for(int i = 0; i < (len >> 1) - 1; ++i) a[i] = 1ll * A[i + 1] * (i + 1) % mod;
for(int i = (len >> 1); i < len; ++i) a[i] = b[i] = 0;
mul(a, b, len);
for(int i = 1; i < (len >> 1); ++i) B[i] = 1ll * a[i - 1] * qpow(i, mod - 2) % mod;
B[0] = 0;
for(int i = 0; i < len; ++i) a[i] = A[i], A[i] = 0;
for(int i = 0; i < len; ++i) b[i] = B[i], B[i] = 0;
}
void EXP(int *a, int *b, int len) {
static int A[N], B[N];
for(int i = 0; i < len; ++i) A[i] = a[i], a[i] = 0;
for(int i = 0; i < len; ++i) B[i] = b[i], b[i] = 0;
B[0] = 1;
for(int j = 2; j < len; j <<= 1) {
for(int i = 0; i < (j << 1); ++i) a[i] = b[i] = 0;
for(int i = 0; i < j; ++i) a[i] = B[i];
LN(a, b, j << 1);
for(int i = j; i < (j << 1); ++i) b[i] = 0;
for(int i = 0; i < j; ++i) b[i] = del(A[i], b[i]);
b[0] = add(b[0], 1);
mul(a, b, j << 1);
for(int i = 0; i < j; ++i) B[i] = a[i];
for(int i = j; i < (j << 1); ++i) B[i] = 0;
}
for(int i = 0; i < len; ++i) a[i] = A[i], A[i] = 0;
for(int i = 0; i < len; ++i) b[i] = B[i], B[i] = 0;
}
void SQRT(int *a, int *b, int len) {
static int A[N], B[N];
for(int i = 0; i < len; ++i) A[i] = a[i], a[i] = 0;
for(int i = 0; i < len; ++i) B[i] = b[i], b[i] = 0;
B[0] = 1;
for(int j = 2; j < len; j <<= 1) {
for(int i = 0; i < (j << 1); ++i) a[i] = b[i] = 0;
for(int i = 0; i < (j >> 1); ++i) a[i] = b[i] = B[i];
mul(a, b, j);
for(int i = 0; i < j; ++i) a[i] = (a[i] + A[i]) % mod;
for(int i = 0; i < (j >> 1); ++i) b[i] = 2ll * B[i] % mod;
for(int i = (j >> 1); i < j; ++i) b[i] = 0;
INV(b, B, j << 1);
for(int i = j; i < (j << 1); ++i) B[i] = 0;
mul(a, B, j << 1);
for(int i = 0; i < j; ++i) B[i] = a[i];
for(int i = j; i < (j << 1); ++i) B[i] = 0;
}
for(int i = 0; i < len; ++i) a[i] = A[i];
for(int i = 0; i < len; ++i) b[i] = B[i];
}
void QPOW(int *a, int *b, int len, int val) {
LN(a, b, len);
for(int i = 0; i < (len >> 1); ++i) b[i] = 1ll * b[i] * val % mod;
EXP(b, a, len);
for(int i = 0; i < (len >> 1); ++i) b[i] = a[i];
}
void init() {while(mx <= n + n) mx <<= 1;}
}F, G;
int n, k;
int main() {
scanf("%d%d", &n, &k); int mem = k; k = min(k, n);
G.n = F.n = k; F.init(); G.init();
G.f[0] = 1; G.f[1] = 6; G.f[2] = 1;
G.SQRT(G.f, G.g, G.mx);
for(int i = 0; i < G.mx; ++i) G.f[i] = 0;
for(int i = G.n + 1; i < G.mx; ++i) G.g[i] = 0;
G.INV(G.g, G.f, G.mx);
for(int i = 0; i < G.mx; ++i) F.f[i] = G.g[i];
F.f[0] = add(F.f[0], 1); F.f[1] = add(F.f[1], 1);
for(int i = 0; i < F.mx; ++i) F.f[i] = 1ll * F.f[i] * 499122177 % mod;
F.QPOW(F.f, F.g, F.mx, n + 1);
for(int i = F.n + 1; i < F.mx; ++i) F.f[i] = 0;
F.mul(F.f, G.f, F.mx);
for(int i = F.n + 1; i < F.mx; ++i) F.f[i] = 0;
for(int i = 1; i <= mem; ++i) printf("%d ", F.f[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具