这里是欢乐的进香河,这里是欢乐的幼儿园。
今天是 2 月 14 日,星期二。在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着。校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们。听到这个消息,所有同学都安安静静地排好了队,大家都知道,校长最不喜欢调皮的孩子。 同学们依次排成了一列,其中有 A位小朋友,有三个共同的欢乐系数 O,S 和 U。如果有一位小朋友得到了 x 个糖果,那么他的欢乐程度就是 f(x)=O*x2+S*x+U。
现在校长开始分糖果了,一共有 M个糖果。有些小朋友可能得不到糖果,对于那些得不到糖果的小朋友来说,欢乐程度就是 1。如果一位小朋友得不到糖果,那么在他的身后的小朋友也都得不到糖果。 (即这一列得不到糖果的小朋友一定是最后的连续若干位) 所有分糖果的方案都是等概率的。现在的问题是:期望情况下,所有小朋友的欢乐程度的乘积是多少?
呆呆同学很快就有了一个思路,只要知道总的方案 T 和所有方案下欢乐程度乘积的总和 S,就可以得到答案 Ans=S/T。现在他已经求出来了 T的答案,但是 S 怎么求呢?他就不知道了,你能告诉他么?
因为答案很大,你只需要告诉他 S对 P 取模后的结果。
后记:
虽然大家都知道,即便知道了 T,知道了 S 对 P 取模后的结果,也没有办法知道期望情况下,所以小朋友欢乐程度的乘积。但是,当呆呆想到这一点的时候,已经彻底绝望了。
M<=10000,P<=255,A<=10^8,O<=4,S<=300,U<=100。
设 fi,j 表示有i个人,吃了j个零食的乘积和。
那么 f1,i=o∗i2+s∗i+u
如果把 fi 看作一个多项式,那么 fi=(f1)i
答案要求 ∑ni=1fi,m
可以用数位dp+FFT来做。
数位dp的话既可以从高位到低位,也可以从低位到高位,维护几个东西,这个是最经典的数位dp。
但是因为好久没写了,写错了。
注意p非常小,所以可以直接NTT。
Code:
#include
#include
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define ff(i, x, y) for(int i = x; i < y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
const int mo = 998244353, N = 4e5 + 5;
ll n, m, p, A, o, s, u;
ll s1[N], s0[N], s2[N], re[N], g[N], li[N];
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;
}
ll w[N], tx;
void dft(ll *a) {
ff(i, 0, n) {
int p = i, q = 0;
fo(j, 1, tx) q = q * 2 + p % 2, p /= 2;
if(q > i) swap(a[q], a[i]);
}
for(int m = 2; m <= n; m *= 2) {
int h = m / 2;
ff(i, 0, h) {
ll W = w[i * (n / m)];
for(int j = i; j < n; j += m) {
int k = j + h;
ll u = a[j], v = a[k] * W % mo;
a[j] = (u + v) % mo, a[k] = (u - v + mo) % mo;
}
}
}
}
void fft(ll *a, ll *b) {
ll v = ksm(3, (mo - 1) / n);
w[0] = 1; fo(i, 1, n) w[i] = w[i - 1] * v % mo;
dft(a); dft(b);
ff(i, 0, n) a[i] = a[i] * b[i] % mo;
fo(i, 0, n / 2) swap(w[i], w[n - i]);
dft(a); ll ni = ksm(n, mo - 2);
ff(i, 0, n) a[i] = a[i] * ni % mo;
}
int main() {
scanf("%lld %lld %lld %lld %lld %lld", &m, &p, &A, &o, &s, &u);
fo(i, 1, m) g[i] = ((ll) i * i * o + (ll) i * s + u) % p;
A = min(A, m);
tx = 0; while(1 << tx ++ <= m); n = 1 << tx;
s1[0] = 1;
for(; A; A /= 2) {
if(A & 1) {
ff(i, 0, n) re[i] = g[i];
re[0] ++; fft(s0, re);
ff(i, 0, n) if(i > m) s0[i] = 0; else s0[i] %= p;
ff(i, 0, n) s0[i] = (s0[i] + s1[i] + s2[i]) % p;
ff(i, 0, n) re[i] = g[i]; fft(s1, re);
ff(i, 0, n) if(i > m) s1[i] = 0; else s1[i] %= p;
ff(i, 0, n) re[i] = g[i]; fft(s2, re);
ff(i, 0, n) if(i > m) s2[i] = 0; else s2[i] %= p;
} else {
ff(i, 0, n) li[i] = s2[i];
ff(i, 0, n) s2[i] = (s0[i] + s1[i] + s2[i]) % p;
ff(i, 0, n) re[i] = g[i];
fft(s2, re);
ff(i, 0, n) if(i > m) s2[i] = 0; else s2[i] = (s2[i] + li[i]) % p;
}
ff(i, 0, n) re[i] = g[i];
fft(g, re);
ff(i, 0, n) if(i > m) g[i] = 0; else g[i] %= p;
}
printf("%lld", (s0[m] + s1[m]) % p);
}