LOJ 6261 一个人的高三楼

LINK:一个人的高三楼

求一个数列的K次前缀和。

\(n\leq 100000,k\leq 2^60\)

前缀和K次。这类似于多项式卷积。

构造 普通型生成函数F(x)表示数列中的每一项 0次前缀和F(x)=\sum_{i=0}{n-1}a_{i+1}x^i

考虑如何生成1次前缀和 构造多项式G(x).

使得 F(x)[0]×G(x)=F(x)[1].

可以比较显然的得到\(G(x)=\sum_{i=0}{n-1}x^i\)

所以所求为F(x)×(G(x))^k.

多项式快速幂 复杂度nlognlogk.常数过大过不了。

由于G(x)这个多项式的系数的特殊性 考虑O(1)求出\(G(x)^k\)的各项系数。

我们只要前n-1项 对于第i项的系数 有K个多项式的某项系数提供 可以写成 \(\sum_{i=1}{k}w_i=i\)

显然是隔板法 系数为C(i+k-1,k-1)=C(i+k-1,i).

直接求不太好求 但是 这些系数是递增的 如C(i+k-1,i),C(i+1+k-1,i+1),C(i+2+k-1,i+2)...

第一项好求为1 第二项可以由第一项推出来。

所以总复杂度 nlogn.

//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ldb long double
#define pb push_back
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE ll i=p;i<=n;++i)
#define go(x) for(ll i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE ll i=n;i>=p;--i)
#define pii pair<ll,ll> 
#define mk make_pair
#define mod 998244353
#define RE register
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define ull unsigned long long
#define P 1000000000000000ll
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline ll read()
{
	RE ll x=0,f=1;char ch=getc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
	return x*f;
}
const ll MAXN=300010,G=3;
ll n,k,lim;
ll a[MAXN],b[MAXN],rev[MAXN];
ll ksm(ll b,ll p)
{
	b=b%mod;ll cnt=1;
	while(p)
	{
		if(p&1)cnt=cnt*b%mod;
		b=b*b%mod;p=p>>1;
	}
	return cnt;
}
inline void NTT(ll *a,ll op)
{
	rep(0,lim-1,i)if(rev[i]<i)swap(a[i],a[rev[i]]);
	for(ll len=2;len<=lim;len=len<<1)
	{
		ll mid=len>>1;
		ll wn=ksm(G,op==1?(mod-1)/len:mod-1-(mod-1)/len);
		for(ll j=0;j<lim;j+=len)
		{
			ll d=1;
			for(ll i=0;i<mid;++i)
			{
				ll x=a[i+j],y=a[i+j+mid]*d%mod;
				a[i+j]=(x+y)%mod;a[i+j+mid]=(x-y+mod)%mod;
				d=d*wn%mod;
			}
		}
	}
	if(op==-1)
	{
		ll inv=ksm(lim,mod-2);
		rep(0,lim-1,i)a[i]=a[i]*inv%mod;
	}
}
signed main()
{
	freopen("1.in","r",stdin);
	get(n);get(k);b[0]=1;
	rep(0,n-1,i)get(a[i]);
	if(!k){rep(0,n-1,i)putl(a[i]);return 0;}
	rep(1,n-1,i)b[i]=(b[i-1]+b[i-1]*ksm(i,mod-2)%mod*((k-1)%mod)%mod)%mod;
	//b[i]=C(i+k-1,i)=C(i+k-2,i-1)+C(i+k-2,i);
	lim=1;while(lim<n+n)lim=lim<<1;
	rep(1,lim-1,i)rev[i]=rev[i>>1]>>1|((i&1)?lim>>1:0);
	NTT(a,1);NTT(b,1);
	rep(0,lim-1,i)a[i]=a[i]*b[i]%mod;
	NTT(a,-1);
	rep(0,n-1,i)putl(a[i]);
	return 0;
}

NTT好久没打了 所以调了1h.

猜你喜欢

转载自www.cnblogs.com/chdy/p/12622403.html