LuoguP5488 差分与前缀和 (多项式 组合数学 生成函数)
前置知识:
二项式定理
杨辉三角 第n行第m个数为C n-1, m-1
- 把前缀和 化成卷积的形式:
这时一个斜着的杨辉三角
现在我们知道了两种情况下b[i]的系数,因为是组合数,k超级大,所以递推出每一个bi.
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define int long long
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1004535809;
const double PI = acos(-1.0);
ll a[N << 2], b[N << 2];
int limit, L, RR[N << 2];
ll qpow(ll a, ll b)
{
ll res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res % mod;
}
const int G = 3;
ll inv(ll x) {return qpow(x, mod - 2);}
void NTT(ll *A, int type)
{
for(int i = 0; i < limit; ++ i)
if(i < RR[i])
swap(A[i], A[RR[i]]);
for(int mid = 1; mid < limit; mid <<= 1) {//原根代替单位根
//ll wn = qpow(type == 1 ? G : Gi, (p - 1) / (mid << 1));
ll wn = qpow(G, (mod - 1) / (mid * 2));
if(type == -1) wn = qpow(wn, mod - 2); //wn的-1次方
//如果超时了上面if这句话删掉,在下面的if(type == -1)里加上下面这个循环
/*for (int i = 1; i < limit / 2; i ++)
swap(A[i], A[limit - i]); */
//逆变换则乘上逆元,因为我们算出来的公式中逆变换是(a^-ij),也就是(a^ij)的逆元
for(int pos = 0; pos < limit; pos += mid * 2) {
ll w = 1;
for(int j = 0; j < mid; ++ j, w = (w * wn) % mod) {
int x = A[pos + j], y = w * A[pos + mid + j] % mod;
A[pos + j] = (x + y) % mod;
A[pos + j + mid] = (x - y + mod) % mod;
}
}
}
if(type == -1) {
ll limit_inv = inv(limit);//N的逆元(N是limit, 指的是2的整数幂)
for(int i = 0; i < limit; ++ i)
A[i] = (A[i] * limit_inv) % mod;//NTT还是要除以n的,但是这里把除换成逆元了,inv就是n在模p意义下的逆元
}
}
void poly_mul(ll *a, ll *b, int deg)
{
for(limit = 1, L = 0; limit <= deg; limit <<= 1) L ++ ;
for(int i = 0; i < limit; ++ i) {
RR[i] = (RR[i >> 1] >> 1) | ((i & 1) << (L - 1));
}
NTT(a, 1);
NTT(b, 1);
for(int i = 0; i < limit; ++ i) a[i] = a[i] * b[i] % mod;
NTT(a, -1);
}
int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0', s %= mod, ch=getchar();
return s*w;
}
signed main () {
ll n, k, opt;
n = read(), k =read(), opt = read();
-- n;
for ( int i = 0; i <= n; ++ i ) {
a[i] = read();
}
b[0] = 1;
if ( !opt ) {
for ( int i = 1; i <= n; ++ i ) {
b[i] = b[i - 1] * qpow( i, mod - 2) % mod * (k + i - 1) % mod;
}
} else {
for ( int i = 1; i <= n; ++ i ) {
b[i] = (b[i - 1] * qpow( i, mod - 2) % mod * ( k - i + 1) % mod * -1 + mod) % mod;
}
}
poly_mul(a, b, n + n);
for ( int i = 0; i <= n; ++ i ) cout << a[i] << ' ';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步