题意:(复制sunset的)有\(T\)天,每天有\(K\)个小时,第\(i\)天有\(D+i−1\)道菜,第一个小时你选择\(L\)道菜吃,接下来每个小时你可以选择吃一道菜或者选择\(A\)个活动中的一个参加,不能连续两个小时吃菜,问每天的方案数之和。\(K\),\(A\)预先给定,\(Q\)次询问,每次给\(D\),\(L\),\(T\)。

题解:显然\(ans=\sum_{i=D}^{D+T-1}\binom{i}{L}F(i)\),其中\(F(i)\)是一个不超过\(k-1\)次的多项式。

把组合数暴力拆开,变为\(\sum_{i=D}^{D+T-1}\frac{i!}{L!(i-L)!}F(i)\)。因为有阶乘,所以考虑把\(F(i)\)写成上升幂多项式的形式来消掉阶乘。具体地,设\(F(x)=\sum_{i=0}^{k-1}a_i(x+1)\dots(x+i)=\sum_{i=0}^{k-1}a_i\frac{(x+i)!}{x!}\),则\(ans=\frac{1}{L!}\sum_{i=D}^{D+T-1}\sum_{j=0}^{k-1}a_j\frac{(i+j)!}{(i-L)!}\)。考虑在\(\frac{(i+j)!}{(i-L)!}\)的分母处补上\((j+L)!\)变为组合数,则\(ans=\frac{1}{L!} \sum_{j=0}^{k-1}a_j(j+L)!\sum_{i=D}^{D+T-1}\binom{i+j}{j+L}\)。后面是组合数上指标求和,可以\(O(1)\)计算。

剩下的问题是怎样求\(a\)。上升幂多项式可以考虑用连续点值来求。具体地,假设我们求出了\(F(-1),F(-2),\dots,F(-k)\),显然有式子\(F(-u)=\sum_{i=0}^{u-1}\frac{(u-1)!}{(u-1-i)!}(-1)^ia_i\)。设\(x_i=(-1)^ia_i,y_i=\frac{1}{i!},z_i=F(-(u+1))\),则\(Z=X*Y,X=\frac{Z}{Y}\)。多项式求逆即可。(其实可以不用求逆,可以发现\(Y=e^x,Y^{-1}=e^{-x}\)。)

剩下的问题是怎样求点值。设\(b_i\)为考虑了前\(i\)个小时的方案数,对于要求的点值\(x\),有递推式\(b_i=Ab_{i-1}+Axb_{i-2}\),可以用矩阵快速幂在\(O(\log k)\)的时间内求出单个点值。

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e6 + 10;
const int M = 1e7 + 1e5 + 10;
const db pi = acos(-1); int k, a, mod, q, l, r[N], fac[M], inv[M], ifac[M], x[N], y[N], z[N]; int gi() {
int x = 0, o = 1;
char ch = getchar();
while((ch < '0' || ch > '9') && ch != '-') {
ch = getchar();
}
if(ch == '-') {
o = -1, ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0', ch = getchar();
}
return x * o;
} struct com {
db x, y;
com(db x = 0, db y = 0): x(x), y(y) {}
com operator+(const com &A) const {
return com(x + A.x, y + A.y);
}
com operator-(const com &A) const {
return com(x - A.x, y - A.y);
}
com operator*(const com &A) const {
return com(x * A.x - y * A.y, x * A.y + y * A.x);
}
com conj() {
return com(x, -y);
}
} w[N]; void init(int n) {
l = 0;
for(int i = 1; i < n; i <<= 1) {
++l;
}
for(int i = 0; i < n; i++) {
r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1)), w[i] = com(cos(pi * i / n), sin(pi * i / n));
}
} void FFT(com *a, int n) {
for(int i = 0; i < n; i++) if(i < r[i]) {
swap(a[i], a[r[i]]);
}
for(int i = 1; i < n; i <<= 1)
for(int p = i << 1, j = 0; j < n; j += p)
for(int k = 0; k < i; k++) {
com x = a[j + k], y = w[n / i * k] * a[j + k + i];
a[j + k] = x + y, a[j + k + i] = x - y;
}
} void mul(int *a, int *b, int *c, int n) {
static com s1[N], s2[N], s3[N], s4[N], s5[N], s6[N];
init(n);
for(int i = 0; i < n; i++) {
s1[i] = com(a[i] & 32767, a[i] >> 15);
s2[i] = com(b[i] & 32767, b[i] >> 15);
}
FFT(s1, n), FFT(s2, n);
for(int i = 0; i < n; i++) {
int j = (n - 1) & (n - i);
com da = (s1[i] + s1[j].conj()) * com(0.5, 0);
com db = (s1[i] - s1[j].conj()) * com(0, -0.5);
com dc = (s2[i] + s2[j].conj()) * com(0.5, 0);
com dd = (s2[i] - s2[j].conj()) * com(0, -0.5);
s3[i] = da * dc, s4[i] = da * dd, s5[i] = db * dc, s6[i] = db * dd;
}
for(int i = 0; i < n; i++) {
s1[i] = s3[i] + s4[i] * com(0, 1);
s2[i] = s5[i] + s6[i] * com(0, 1);
}
FFT(s1, n), FFT(s2, n);
reverse(s1 + 1, s1 + n), reverse(s2 + 1, s2 + n);
for(int i = 0; i < n; i++) {
int da = (ll)(s1[i].x / n + 0.5) % mod;
int db = (ll)(s1[i].y / n + 0.5) % mod;
int dc = (ll)(s2[i].x / n + 0.5) % mod;
int dd = (ll)(s2[i].y / n + 0.5) % mod;
c[i] = (da + ((ll)(db + dc) << 15) + ((ll)dd << 30)) % mod;
}
} struct mat {
int v[2][2];
mat() {
memset(v, 0, sizeof(v));
}
mat operator*(const mat &A) const {
mat ret;
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++) {
ull tmp = 0;
for(int k = 0; k < 2; k++) {
tmp += 1ll * v[i][k] * A.v[k][j];
}
ret.v[i][j] = tmp % mod;
}
return ret;
}
} S, T; mat qpow(mat a, int b) {
mat ret;
for(int i = 0; i < 2; i++) {
ret.v[i][i] = 1;
}
while(b) {
if(b & 1) {
ret = ret * a;
}
a = a * a, b >>= 1;
}
return ret;
} void init() {
const int n = 1e7 + 1e5 + 1;
fac[0] = fac[1] = ifac[0] = ifac[1] = inv[1] = 1;
for(int i = 2; i <= n; i++) {
fac[i] = 1ll * fac[i - 1] * i % mod;
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
ifac[i] = 1ll * ifac[i - 1] * inv[i] % mod;
}
} int C(int n, int m) {
if(m < 0 || n < m) {
return 0;
}
return 1ll * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
} int main() {
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
#endif
cin >> k >> a >> mod >> q;
init();
S.v[0][0] = 1, S.v[0][1] = a, T.v[1][0] = 1, T.v[1][1] = a;
for(int i = 0; i < k; i++) {
T.v[0][1] = 1ll * a * (mod - i - 1) % mod;
z[i] = 1ll * (S * qpow(T, k - 1)).v[0][0] * ifac[i] % mod;
y[i] = 1ll * ((i & 1) ? mod - 1 : 1) * ifac[i] % mod;
}
int N = 1;
while(N <= 2 * k - 2) {
N <<= 1;
}
mul(y, z, x, N);
for(int i = 0; i < k; i++) {
x[i] = 1ll * x[i] * ((i & 1) ? mod - 1 : 1) % mod;
}
while(q--) {
int l = gi(), d = gi(), t = gi(), ans = 0;
for(int i = 0; i < k; i++) {
ans = (ans + 1ll * x[i] * fac[i + l] % mod * (C(d + t + i, i + l + 1) - C(d + i, i + l + 1) + mod)) % mod;
}
cout << 1ll * ans*ifac[l] % mod << '\n';
}
return 0;
}

Codechef BINOMSUM的更多相关文章

  1. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  2. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

  3. codechef 两题

    前面做了这场比赛,感觉题目不错,放上来. A题目:对于数组A[],求A[U]&A[V]的最大值,因为数据弱,很多人直接排序再俩俩比较就过了. 其实这道题类似百度之星资格赛第三题XOR SUM, ...

  4. codechef January Challenge 2014 Sereja and Graph

    题目链接:http://www.codechef.com/JAN14/problems/SEAGRP [题意] 给n个点,m条边的无向图,判断是否有一种删边方案使得每个点的度恰好为1. [分析] 从结 ...

  5. BZOJ3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 85[Submit][St ...

  6. CodeChef CBAL

    题面: https://www.codechef.com/problems/CBAL 题解: 可以发现,我们关心的仅仅是每个字符出现次数的奇偶性,而且字符集大小仅有 26, 所以我们状态压缩,记 a[ ...

  7. CodeChef FNCS

    题面:https://www.codechef.com/problems/FNCS 题解: 我们考虑对 n 个函数进行分块,设块的大小为S. 每个块内我们维护当前其所有函数值的和,以及数组中每个元素对 ...

  8. codechef Prime Distance On Tree(树分治+FFT)

    题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治 ...

  9. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

随机推荐

  1. Linux学习篇(一)-初识Linux

    开源许可协议 简单了解开源许可协议,一张图读懂. linux 系统特点 linux 特点安全性高.高可用.高性能 稳定且有效率 免费或少许免费 漏洞少且快速修补 多任务多用户 更加安全的用户及文件权限 ...

  2. PHP-密码和token

    密码 直接 md5 和 sha1 不安全!!! crypt() 和 hash_equals(): http://php.net/manual/zh/function.crypt.php <?ph ...

  3. Spring cloud gateway自定义filter以及负载均衡

    自定义全局filter package com.example.demo; import java.nio.charset.StandardCharsets; import org.apache.co ...

  4. JSP 学习笔记1

    JSP 学习笔记   JSP是Servlet的一种特殊形式,每个JSP页面就是一个Servlet实例--JSP页面有系统编译成Servlet,Servlet再负责响应用户请求. 1.JSP注释 < ...

  5. vue-过滤器(filter)

    1.全局过滤器(项目中所有的vue文件都可以使用) 1.1  直接注册全局过滤器 在main.js中注册: 在项目中使用; 前面的为时间,作为filter过滤器的第一个参数. 1.2 所有过滤器写在一 ...

  6. cts-on-gsi测试流程

    测试前提: 1.发货user版本 2.selinux:Enable 3.连接ADB,stay awake 4.烧录XXX申请的key 5.外网环境(ipv6) ATV9测试准备(正常准备环境+fast ...

  7. Pikachu漏洞练习平台实验——SQL注入(四)

    1.概述 1.1发生原因 SQL注入漏洞,主要是开发人员在构建代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信息泄 ...

  8. react 渲染顺序

    工作中要对一个表格做再次更新, 可能是渲染后更新或者部分组件渲染之后, 对页面效果做处理 之前对react的理解, 仅仅停留在render渲染. 这次好好理解了下react的生命周期 1 react组 ...

  9. MYSQL学习笔记/2019

    以下内容均为转载,只是方便今后学习:如有不妥,请联系删除:特此感谢原博主精心制作!(文章底部贴有原文链接) /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ m ...

  10. java_第一年_JavaWeb(2)

    HTTP协议 HTTP协议——超文本传输协议,用于定义web浏览器和web服务器之间数据交换的过程,遵守一定的通讯的格式: HTTP请求——包括请求行和多个信息头 请求行:包含请求方式(常用的GET. ...