Codechef:Walk on Tree/TREEWALK(Berlekamp-Massey算法)

传送门

题解:
O ( n 3 log k ) O(n^3 \log k) 的优化应该都会。

然后 O ( n 2 ) O(n^2) 用BM求出递推式之后再 O ( n 2 log k ) O(n^2 \log k) 用特征多项式优化一下就行了。

这里说一下这个为啥有递推式,我们要求 S ( A k ) S(A^k) S S 表示对其某些位置求和,由特征多项式是零化多项式可以知道 S ( A k ) = S ( A k % Z ) S(A^k) = S(A^k \% Z) ,Z为特征多项式,那么 S ( A k + 1 % Z ) = S ( A k % Z A ) S(A^{k+1}\%Z) = S(A^k \% Z *A) ,相当于整体往后挪了一位。

#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;
}

const int 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;}

const int N=3e3+50, M=6e3+50;
int n,r,k,dp[N][M];
vector <int> g[N];
vector <int> coef;

struct poly {
	vector <int> a;
	poly(int d=0,int t=0) {a.resize(d+1); a[d]=t;}
	inline int& operator [](const int &b) {return a[b];}
	inline const int& operator [](const int &b) const {return a[b];}
	inline int deg() const {return a.size()-1;}
	friend inline poly operator *(const poly &a,const poly &b) {
		poly c(a.deg()+b.deg(),0);
		for(int i=0;i<=a.deg();i++)
			for(int j=0;j<=b.deg();j++)
				c[i+j]=add(c[i+j],mul(a[i],b[j]));
		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]=add(c[i],b[i]);
		return c;
	}
	inline void opt() {
		int d=coef.size()-1;
		for(int i=deg();i>=d;i--) if(a[i])
			for(int j=1;j<=d;j++)
				a[i-j]=add(a[i-j],mul(a[i],coef[j]));
		a.resize(d);
	}
};
namespace bm {
	int L,cnt;
	int a[M],fail[M],delta[M];
	poly R[M];
	inline void pt(poly &vec) {
		for(int i=0;i<=vec.deg();i++) cerr<<vec[i]<<' '; cerr<<'\n';
	}
	inline vector <int> solve() {
		for(int i=1;i<=L;i++) {
			int d=a[i];
			if(cnt) for(int j=1;j<=R[cnt].deg();++j) d=dec(d,mul(R[cnt][j],a[i-j]));
			if(!d) continue;
			fail[cnt]=i; delta[cnt]=d;
			if(!cnt) {
				++cnt;
				R[cnt]=poly(i,0);
			} else {
				int coef=mul(delta[cnt],power(delta[cnt-1],mod-2));
				for(int j=fail[cnt-1]+1;j<i;j++) R[cnt+1].a.push_back(0);
				R[cnt+1].a.push_back(coef); 
				for(int j=1;j<=R[cnt-1].deg();j++) R[cnt+1].a.push_back(mul(mod-coef,R[cnt-1][j]));
				R[cnt+1]=R[cnt+1]+R[cnt]; ++cnt; 
			}
		} return R[cnt].a;
	}
}

int main() {
	n=rd(), bm::L=n*2+15;
	for(int i=1;i<n;i++) {
		int x=rd(), y=rd();
		g[x].push_back(y); 
		g[y].push_back(x);
	} 
	r=rd(), k=rd();
	dp[r][0]=1;
	for(int i=1;i<=bm::L;i++)
		for(int j=1;j<=n;j++)
			for(auto v:g[j])
				dp[v][i]=add(dp[v][i],dp[j][i-1]);
	for(int i=1;i<=bm::L;i++)
		bm::a[i]=dp[r][i-1];
	coef=bm::solve();
	poly f(0,1), g(1,1);
	for(;k;k>>=1,g=g*g,g.opt())
		if(k&1) f=f*g,f.opt();
	for(int i=1;i<=n;i++) {
		int ans=0;
		for(int j=0;j<=f.deg();j++)
			ans=add(ans,mul(f[j],dp[i][j]));
		cout<<ans<<' ';
	}
}
发布了553 篇原创文章 · 获赞 227 · 访问量 24万+

猜你喜欢

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