Description
这里是欢乐的进香河,这里是欢乐的幼儿园。
今天是
2
2
月 日,星期二。在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着。校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们。听到这个消息,所有同学都安安静静地排好了队,大家都知道,校长不喜欢调皮的孩子。
同学们依次排成了一列,其中有
A
A
位小朋友,有三个共同的欢乐系数 和
U
U
。如果有一位小朋友得到了 个糖果,那么她的欢乐程度就是
f(x)=O∗x2+S∗x+U
f
(
x
)
=
O
∗
x
2
+
S
∗
x
+
U
。
现在校长开始分糖果了,一共有
M
M
个糖果。有些小朋友可能得不到糖果,对于那些得不到糖果的小朋友来说,欢乐程度就是 。如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果。(即这一列得不到糖果的小朋友一定是最后的连续若干位)
所有分糖果的方案都是等概率的。现在问题是:期望情况下,所有小朋友的欢乐程度的乘积是多少?呆呆同学很快就有了一个思路,只要知道总的方案个数T和所有方案下欢乐程度乘积的总和
S
S
,就可以得到答案 。现在他已经求出来了
T
T
的答案,但是 怎么求呢?他就不知道了。你能告诉他么?
因为答案很大,你只需要告诉他
S
S
对 取模后的结果。
后记:
虽然大家都知道,即便知道了
T
T
,知道了 对
P
P
取模后的结果,也没有办法知道期望情况下,所有小朋友欢乐程度的乘积。但是,当呆呆想到这一点的时候,已经彻底绝望了。
Input
第一行有 个整数,分别是
M
M
和 。
第二行有一个整数
A
A
,第三行有一个整数 。
第四行有一个整数
S
S
,第五行有一个整数 。
Output
一个整数 S S ,因为答案可能很大,你只需要输出 对 P P 取模后的结果。
Sample Input
4 100
4
1
0
0
Sample Output
63
样例说明
函数 。一共有 4 4 份零食, 位同学。如果只有第一个同学得到,欢乐程度为 16 16 ,若前两位同学得到,欢乐程度的所有可能依次为 9,9,16 9 , 9 , 16 ,若有三位同学得到,欢乐程度有 4,4,4 4 , 4 , 4 ,最后一种情况,每一个同学都得到了零食,欢乐程度为 1 1 。相加后得到 。
HINT
对于 100% 100 % 的数据, M≤10000,P≤255,A≤108,O≤4,S≤300,U≤100 M ≤ 10000 , P ≤ 255 , A ≤ 108 , O ≤ 4 , S ≤ 300 , U ≤ 100 。
题解
首先想到 dp 。
g[i][j]
g
[
i
]
[
j
]
表示前
i
i
个小朋友分到 块糖的所有方案
S
S
之和,然后答案是 。
dp方程
然后发现是个卷积的形式,于是立刻想到 FFT ,立刻想到倍增 (
于是记
则 F[n][m] F [ n ] [ m ] 即为答案。
我们还是可以用倍增的方式求 F[n] F [ n ] (以下设 n n 为 的倍数)。
完成!
对于
n mod 2=1
n
m
o
d
2
=
1
的情况,可以从
F[n−1]
F
[
n
−
1
]
来计算
F[n]
F
[
n
]
。可以证明,迭代次数是
log2n
l
o
g
2
n
级别的。
于是就可以开心的使用倍增完成,取膜可以在求完卷积时膜。
OSU是坠吼的
复杂度 O(nlog2nlog2m) O ( n log 2 n log 2 m )
My Code
/**************************************************************
Problem: 4332
User: infinityedge
Language: C++
Result: Accepted
Time:3868 ms
Memory:4364 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <complex>
#define MAXN 32768
#define pi acos(-1)
using namespace std;
typedef long long ll;
typedef complex<double> E;
int p;
void bit_reverse(int n, E* r){
for(int i = 0, j = 0; i < n; i ++){
if(i > j) swap(r[i], r[j]);
for(int l = n >> 1; (j ^= l) < l; l >>= 1);
}
}
void fft(int n, E* r, int f){
bit_reverse(n, r);
for(int i = 2; i <= n; i <<= 1){
int m = i >> 1;
for(int j = 0; j < n; j += i){
E w(1, 0), wn(cos(2 * pi / i), f * sin(2 * pi / i));
for(int k = 0; k < m; k ++){
E z = r[j + m + k] * w;
r[j + m + k] = r[j + k] - z;
r[j + k] = r[j + k] + z;
w = w * wn;
}
}
}
if(f == -1){
for(int i = 0; i < n; i ++) r[i] /= n, r[i] = int(r[i].real() + 0.1) % p;
}
}
int m, n, o, s, u, N;
E F[MAXN], tmp[MAXN];
void solve(E* f, E* g, int n){
if(n == 0){
g[0] = 1; return;
}
if(n % 2 == 1){
solve(f, g, n - 1);
fft(N, g, 1);
for(int i = 0; i < N; i ++) g[i] = g[i] * F[i];
fft(N, g, -1);
for(int i = 0; i <= m; i ++) f[i] = f[i] + g[i], f[i] = int(f[i].real() + 0.1) % p;
for(int i = m + 1; i < N; i ++) g[i] = 0;
}else{
solve(f, g, n / 2);
for(int i = 0; i < N; i ++) tmp[i] = f[i];
fft(N, tmp, 1);
fft(N, g, 1);
for(int i = 0; i < N; i ++) tmp[i] = tmp[i] * g[i];
fft(N, tmp, -1);
for(int i = 0; i < N; i ++) g[i] = g[i] * g[i];
fft(N, g, -1);
for(int i = 0; i <= m; i ++) f[i] = f[i] + tmp[i], f[i] = int(f[i].real() + 0.1) % p;
for(int i = m + 1; i < N; i ++) g[i] = 0;
}
}
E a[MAXN], b[MAXN];
E g[MAXN], f[MAXN];
int main(){
scanf("%d%d%d%d%d%d", &m, &p, &n, &o, &s, &u);
N = 1; while(N < 2 * m + 1) N = N << 1;
for(int i = 1; i <= m; i ++){
F[i] = (o * i * i + s * i + u) % p;
}
fft(N, F, 1);
solve(f, g, n);
printf("%d\n", int(f[m].real() + 0.1));
return 0;
}