Comet OJ - Contest #11 E ffort(组合计数+多项式快速幂)
题解:
考虑若最后的总伤害数是s,那么就挡板分配一下,方案数是\(C_{s-1}^{n-1}\)。
那么问题在于总伤害数很大,不能一个一个的算。
\(C_{s-1}^{n-1}\)的OGF是\({x^{n-1}\over (1-x)^n}\)
由\(F=FA+R->F={R \over 1-A}\)
得到递推式\(A=1-(1-x)^n\),前面的项可以用组合数算出。
那么每次就是常系数齐次递推,每次搞的时候取模就好了。
复杂度是\(O(log^2)\)
题解给出了更加巧妙的方法,我们不直接求\(s\)伤害的方案数。
考虑\(f(x)\)表示任意伤害下, 分配给x个人的方案数。
当合并\(f、g\)两堆伤害时时,由于中间可以攃挡板,可以不插,所以就是\(f*g*(1+x)\)。
用NTT卷积,每次算完后只用保留前n项。
直接套快速幂是\(O(log^2)\)的,但是可以用exp优化。
初值利用这个式子就好了\(\sum_{i=y}^xC_{i}^y=C_{x+1}^{y+1}\)。
直到现在我才意识到杨辉三角的一条对角线和一列的求法是一样的,由于翻转一下就好了。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 998244353;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
typedef vector<ll> V;
#define pb push_back
#define si size()
#define re resize
namespace ntt {
const int nm = 262144;
ll w[nm], a[nm], b[nm]; int r[nm];
void build() {
for(int i = 1; i < nm; i *= 2) {
w[i] = 1;
ll v = ksm(3, (mo - 1) / 2 / i);
ff(j, 1, i) w[i + j] = w[i + j - 1] * v % mo;
}
}
void dft(ll *a, int n, int f) {
ff(i, 0, n) {
r[i] = r[i / 2] / 2 + (i & 1) * (n / 2);
if(i < r[i]) swap(a[i], a[r[i]]);
} ll b;
for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i) ff(k, 0, i)
b = a[i + j + k] * w[i + k], a[i + j + k] = (a[j + k] - b) % mo, a[j + k] = (a[j + k] + b) % mo;
if(f == -1) {
reverse(a + 1, a + n);
b = ksm(n, mo - 2);
ff(i, 0, n) a[i] = (a[i] + mo) * b % mo;
}
}
V operator * (V p, V q) {
int n0 = p.si + q.si - 1, n = 1;
while(n < n0) n *= 2;
ff(i, 0, n) a[i] = b[i] = 0;
ff(i, 0, p.si) a[i] = p[i];
ff(i, 0, q.si) b[i] = q[i];
dft(a, n, 1); dft(b, n, 1);
ff(i, 0, n) a[i] = a[i] * b[i] % mo;
dft(a, n, -1);
p.re(n0);
ff(i, 0, n0) p[i] = a[i];
return p;
}
void dft(V &p, int f) {
int n = p.si;
ff(i, 0, n) a[i] = p[i];
dft(a, n, f);
ff(i, 0, n) p[i] = a[i];
}
}
using ntt :: operator *;
using ntt :: dft;
V qni(V a) {
V b; b.re(1); b[0] = ksm(a[0], mo - 2);
for(int n = 2; n < a.si * 2; n *= 2) {
V c = a; c.re(n); c.re(2 * n); dft(c, 1);
b.re(2 * n); dft(b, 1);
ff(i, 0, 2 * n) b[i] = (2 * b[i] - c[i] * b[i] % mo * b[i]) % mo;
dft(b, -1); b.re(n);
}
b.re(a.si); return b;
}
V qd(V a) {
fo(i, 0, a.si - 2) a[i] = a[i + 1] * (i + 1) % mo;
a.re(a.si - 1);
return a;
}
V jf(V a) {
a.re(a.si + 1);
fd(i, a.si - 1, 1) a[i] = a[i - 1] * ksm(i, mo - 2) % mo;
a[0] = 0;
return a;
}
V ln(V a) {
int n = a.si;
a = jf(qd(a) * qni(a));
a.re(n);
return a;
}
V exp(V a) {
V b; b.re(1); b[0] = 1;
for(int n = 1; n < a.si * 2; n *= 2) {
b.re(n);
V c = a; c.re(n);
V d = ln(b);
ff(i, 0, n) d[i] -= c[i];
d = d * b;
ff(i, 0, n) b[i] = (b[i] - d[i] + mo) % mo;
}
b.re(a.si); return b;
}
const int N = 1e5 + 5;
int n, m, a[N], b[N];
ll fac[N], nf[N];
void build(int n) {
fac[0] = 1;
fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
nf[n] = ksm(fac[n], mo - 2);
fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
}
V p;
V mul(V a, V b) {
a = a * b;
a.re(m);
fd(i, m - 1, 1) a[i] = (a[i] + a[i - 1]) % mo;
return a;
}
V c;
V ksm(V x, int y) {
if(y == 1) return x;
ll xc = x[0]; ll nc = ksm(xc, mo - 2);
ff(i, 0, m) x[i] = x[i] * nc % mo;
x = ln(x);
ff(i, 0, m) x[i] = x[i] * y % mo;
x = exp(x);
xc = ksm(xc, y);
ff(i, 0, m) x[i] = x[i] * xc % mo;
V d = c;
ff(i, 0, m) d[i] = d[i] * (y - 1) % mo;
d = exp(d);
x = x * d; x.re(m);
return x;
}
V operator + (V a, V b) {
if(a.si < b.si) a.re(b.si);
ff(i, 0, b.si) a[i] = (a[i] + b[i]) % mo;
return a;
}
V ans;
int main() {
ntt :: build();
build(1e5);
scanf("%d %d", &m, &n);
c.re(2); c[0] = 1; c[1] = 1;
c.re(m); c = ln(c);
fo(i, 1, n) scanf("%d %d", &a[i], &b[i]);
fo(i, 1, n) {
p.clear(); p.re(m);
ll f = 1;
fo(j, 1, min(b[i], m)) {
f = f * (b[i] - j + 1) % mo;
p[j - 1] = f * nf[j] % mo;
}
p = ksm(p, a[i]);
if(i == 1) ans = p; else ans = mul(ans, p);
}
ll as = (ans[m - 1] % mo + mo ) % mo;
pp("%lld\n", as);
}
Comet OJ - Contest #11 E ffort(组合计数+多项式快速幂)的更多相关文章
- Comet OJ - Contest #11 题解&赛后总结
Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...
- Comet OJ - Contest #11题解
传送门 \(A\) 咕咕咕 const int N=1e6+5; char s[N],t[N];int n,res; inline bool cmp(const int &x,const in ...
- Comet OJ - Contest #11 B题 usiness
###题目链接### 题目大意:一开始手上有 0 个节点,有 n 天抉择,m 种方案,在每天中可以选择任意种方案.任意次地花费 x 个节点(手上的节点数不能为负),使得在 n 天结束后,获得 y 个节 ...
- Comet OJ - Contest #11 B 背包dp
Code: #include <bits/stdc++.h> #define N 1005 #define M 2000 #define setIO(s) freopen(s". ...
- Comet OJ - Contest #11 A 水题
Code: #include <bits/stdc++.h> #define N 3000000 using namespace std; char str[N]; int main() ...
- Comet OJ - Contest #11 D isaster 重构树+倍增+dfs序+线段树
发现对于任意一条边,起决定性作用的是节点编号更大的点. 于是,对于每一条边,按照节点编号较大值作为边权,按照最小生成树的方式插入即可. 最后用线段树维护 dfs 序做一个区间查询即可. Code: # ...
- Comet OJ - Contest #2 简要题解
Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...
- Comet OJ - Contest #2简要题解
Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...
- Comet OJ - Contest #4--前缀和
原题:Comet OJ - Contest #4-B https://www.cometoj.com/contest/39/problem/B?problem_id=1577传送门 一开始就想着暴力打 ...
随机推荐
- 配置框架spring和SpringDataJpa整合----员工是爹
<!-- 1.dataSource 配置数据库连接池--> <bean id="dataSource" class="com.mchange.v2.c3 ...
- 阿里云移动研发平台EMAS,是如何连续5年安全护航双11的?
摘要: 阿里云作为阿里巴巴IT基础设施的基石,每年的双十一都面临前所未有的巨大技术挑战.阿里云的EMAS移动研发平台,连续5年支持双11,不仅保障了手机淘宝.支付宝这些阿里巴巴集团App的使用体验,也 ...
- [CSP-S模拟测试51]题解
错失人生中第一次AK的机会…… A.attack 支配树板子题.考场上发明成功√ 首先支配树上两点路径之间的点都是必经之点,根据这个性质我们就可以yy出建树的方法.跑拓扑,在每个点(设为$x$)即将入 ...
- CSS入门之盒模型(六分之四)
盒模型要点知识 务必注意看,这可是前端面试 必定会遇到 的问题. box-sizing 盒模型的主要CSS属性,除继承外有两个值: content-box 这里不再细说历史原因,只说其作用. cont ...
- 【Spring Boot】Spring Boot项目部署到外部Tomcat容器
一.修改项目打包方式为war包 修改pom.xml文件中packaging属性项 <packaging>war</packaging> 修改pom.xml文件增加一个依赖 &l ...
- css3动画的性能优化
目前对提升移动端CSS3动画体验的主要方法有几点:尽可能多的利用硬件能力,如使用3D变形来开启GPU加速 -webkit-transform: translate3d(0, 0, 0); -moz-t ...
- Arrays(一)二次封装自己的数组
一.二次封装自己的数组 目标:设计int 类型数组, (1)可以根据用户传入的容量设置数组的长度,如果用户未设置容量,默认设置长度为10(考虑使用多态性) (2)判断数组是否为空 (3)获取数组的容量 ...
- selenium自动化之验证,判断总结(持续更新)
API命令 1,is_displayed() 例子:driver.find_element_by_css_selector("#id").is_displayed() 该元素是否可 ...
- 【git】如何ignore一个文件的更改又保留其初始版本
参考: https://compiledsuccessfully.dev/git-skip-worktree/ https://stackoverflow.com/questions/9794931/ ...
- Spring MVC请求参数绑定 自定义类型转化 和获取原声带额servlet request response信息
首先还在我们的框架的基础上建立文件 在domian下建立Account实体类 import org.springframework.stereotype.Controller; import org. ...