THUPC2017 I :Sum(牛顿恒等式)

题意:
给定数组 A 1 . . . , A n A_1...,A_n ,对于所有 1 i k 1 \le i \le k ,求 S i = j A j i S_i = \sum_{j}A_j^i

题解:
这道题要用到一个叫牛顿恒等式的玩意儿。

对于 n n 次多项式 f = i = 0 n a i x i f=\sum_{i=0}^na_ix^i (注意是首一多项式),设其几个根分别为 x 1 , x 2 , . . . , x n x_1,x_2,...,x_n ,设 b i = a n i b_i =a_{n-i} ,那么对于任意 k k ,有:
j = 1 n S i b n i + k b n = 0 \sum_{j=1}^n S_i b_{n-i}+kb_n = 0

这个东西在 k n k \ge n 的时候只需要把 x i x_i 分别带入 f f 然后相加即可得到,小于的时候可以用归纳法证明(当然我不会)。

然后分治FFT+多项式求逆即可。 时间复杂度 O ( n log 2 n + k log k ) O(n \log^2 n + k \log k)

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}
inline void W(int x) {
	static int buf[50];
	if(!x) {putchar('0'); return;}
	if(x<0) {putchar('-'); x=-x;}
	while(x) {buf[++buf[0]]=x%10; x/=10;}
	while(buf[0]) putchar(buf[buf[0]--]+'0');
}

const int N=2e6+50, mod=998244353;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (long long)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}

namespace FFT {
	int k,w[N],pos[N],A[N],B[N];
	inline void init(int n) {
		for(k=1;k<=n;k<<=1);
		for(int i=1;i<k;i++) 
			pos[i]=(i&1) ? ((pos[i>>1]>>1)^(k>>1)) : (pos[i>>1]>>1);
		memset(A,0,sizeof(int)*k);
		memset(B,0,sizeof(int)*k);
	}
	inline void dft(int *a) {
		for(int i=1;i<k;i++) 
			if(pos[i]>i) swap(a[pos[i]],a[i]);
		for(int bl=1;bl<k;bl<<=1) {
			int tl=bl<<1, wn=power(3,(mod-1)/tl);
			w[0]=1; for(int i=1;i<bl;i++) w[i]=mul(w[i-1],wn);
			for(int bg=0;bg<k;bg+=tl)
				for(int j=0;j<bl;j++) {
					int &t1=a[bg+j],&t2=a[bg+j+bl],t=mul(t2,w[j]);
					t2=dec(t1,t); t1=add(t1,t);
				}
		}
	}
	inline void opt() {
		dft(A); dft(B);
		for(int i=0;i<k;i++) A[i]=mul(A[i],B[i]);
		dft(A); reverse(A+1,A+k);
		const int inv=power(k,mod-2);
		for(int i=0;i<k;i++) A[i]=mul(A[i],inv);
	}
}
struct poly {
	vector <int> a;
	poly(int x=0,int y=0) {a.resize(x+1); a[x]=y;}
	inline int deg() const {return a.size()-1;}
	inline int& operator [](int x) {return a[x];}
	inline const int& operator [](int x) const{return a[x];}
	inline poly extend(int len) {poly c=*this; c.a.resize(len+1); return c;}
	inline poly rev() {poly c=*this; reverse(c.a.begin(),c.a.end()); return c;}
	friend inline poly operator *(const poly &a,const poly &b) {
		poly c(a.deg()+b.deg());
		FFT::init(c.deg());
		for(int i=0;i<=a.deg();i++) FFT::A[i]=a[i];
		for(int i=0;i<=b.deg();i++) FFT::B[i]=b[i];
		FFT::opt();
		for(int i=0;i<=c.deg();i++) c[i]=FFT::A[i];
		return c;
	}
	inline poly mul(int b) {
		poly c=*this;
		for(int i=0;i<=c.deg();i++) c[i]=::mul(c[i],b);
		return c;
	}
	friend inline poly operator -(const poly &a,const poly &b) {
		poly c(max(a.deg(),b.deg()));
		for(int i=0;i<=a.deg();i++) c[i]=add(c[i],a[i]);
		for(int i=0;i<=b.deg();i++) c[i]=dec(c[i],b[i]);
		return c;
	}
	inline poly calc_inv(poly f,int len) {
		if(len==1) {return poly(0,power(f[0],mod-2));}
		poly f0=calc_inv(f.extend(len/2-1),len/2);
		return (f0.mul(2)-(f*f0).extend(len-1)*f0).extend(len-1);
	}
	inline poly calc_inverse(int len) {
		int k; for(k=1;k<=len;k<<=1);
		poly f=*this; f.extend(k);
		return calc_inv(f,k).extend(len);
	}
};

int n,k;
inline poly solve(int l,int r) {
	if(l==r) {
		poly c(1,1); 
		c[0]=dec(0,rd()); 
		return c;
	}
	int mid=(l+r)>>1;
	return solve(l,mid)*solve(mid+1,r);
}
int main() {
	n=rd(), k=rd();
	poly b=solve(1,n);
	b=b.rev(); poly a=b;
	for(int i=0;i<=n;i++) a[i]=mul(b[i],mod-i);	
	a=(a*b.calc_inverse(k)).extend(k);
	for(int i=1;i<=k;i++) W(a[i]), putchar(' ');
}

发布了553 篇原创文章 · 获赞 227 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/83856552