BZOJ1494: [NOI2007]生成树计数(Berlekamp-Massey算法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/84176599

传送门

题解:
直接打表+BM算出递推式,BM具体实现可以戳这里

附上一份其丑无比的BM代码:

const int L=4e2;

namespace bm {
	int cnt,a[N],fail[N],delta[N];
	vector <int> R[N];
	inline void pt(vector <int> &vec) {
		for(int i=1;i<vec.size();i++) cout<<vec[i]<<' '; cout<<'\n';
	}
	inline vector <int> solve() {
		for(int i=0;i<=cnt;i++) R[i].clear(), fail[i]=0, delta[i]=0; 
		cnt=0; R[0].push_back(0);
		for(int i=1;i<=L;i++) {
			int res=a[i];
			for(int j=1;j<R[cnt].size();j++) res=dec(res,mul(R[cnt][j],a[i-j]));
			if(!res) continue;
			delta[cnt]=res; fail[cnt]=i;
			if(!cnt) {
				R[++cnt].resize(i+1);
			} else {
				R[cnt+1].resize(1);
				for(int j=fail[cnt-1]+1;j<i;++j) R[cnt+1].push_back(0);
				int coef=mul(delta[cnt],power(delta[cnt-1],mod-2));
				R[cnt+1].push_back(coef);
				for(int j=1;j<R[cnt-1].size();++j) R[cnt+1].push_back(mul(R[cnt-1][j],mod-coef));
				R[cnt+1].resize(max(R[cnt+1].size(),R[cnt].size()));
				for(int j=1;j<R[cnt].size();++j) R[cnt+1][j]=add(R[cnt+1][j],R[cnt][j]);
				++cnt; 
			}
		} return R[cnt];
	}
}

然后用特征多项式优化一下常系数线性递推即可。

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

const int mod=65521;
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=1000;
int k,d; long long n;
int deg[]={1,3,7,17,45};
int poly[5][233]={{0,1},{0,3,65520,0},{0,5,65518,3,65516,1,0,0},{0,7,65520,65496,31,65469,65437,300,65437,65469,31,65496,65520,7,65520,0,0,0},{0,8,5,65489,40,364,63172,62845,2793,7304,50170,14272,13974,32712,27590,63226,30516,31431,62449,44809,2992,62529,20712,3072,34090,35005,2295,37931,32809,51547,51249,15351,58217,62728,2676,2349,65157,65481,32,65516,65513,1,0,0,0,0}};
int init[5][233]={{0,1,1,1,1,1},{0,1,1,3,8,21,55,144,377,987,2584,6765},{0,1,1,3,16,75,336,1488,6580,29085,63023,43933,20918,23015,29132,48248,31190,4445,16275,15023,62965,65462,41033,7792,9008,11460},{0,1,1,3,16,125,864,5635,35840,29517,48795,64376,52310,4486,28336,8758,64387,31184,24386,924,17339,37190,56290,63519,16901,29810,10951,54377,10900,7194,45196,49203,6552,6577,27252,8776,26557,8650,16129,47857,498,22234,5918,9943,33404,14096,45895,13602,21648,17129,36233,64359,25954,28647,29122,54220,55400,20284,25183,62301,14459,38513,50440,5427},{0,1,1,3,16,125,1296,12005,38927,26915,65410,9167,63054,58705,18773,9079,38064,46824,48121,50048,47533,30210,24390,51276,45393,357,44927,15398,15923,31582,56586,25233,41258,21255,21563,16387,39423,26418,10008,6962,42377,50881,54893,50452,23715,53140,52131,57691,13625,19479,37874,34633,61220,42575,35931,22461,32377,49296,12287,32887,44563,25055,37753,54336,11668,16467,3267,49972,21276,29700,9569,24951,56257,6220,42130,17892,44424,54362,25175,43989,58472,30146,51698,10010,61771,9533,12296,50446,62591,39451,6049,55426,23860,53435,55903,61846,26992,34882,49338,53785,33687,5239,62781,8739,54104,24441,19229,28336,57354,722,59600,33638,10906,14166,2464,40492,6525,6298,5054,65202,3061,21953,33042,62169,413,26688,41534,18905,18514,174,5800,45851,28806,51230,463,39912,14722,33942,62699,9081,721,27566,62212,46167,64399,6451,61130,31757,53456,30645,956,31691,4229,39383,30503,49884,7394,7757,5169,28587,47797,10078,25177,17354,49135,29691,43238,7280,52120,64621,42500,35920,35907,23823}};
int f[N],g[N],h[N];
inline void mul(int *a,int *b) {
	static int tp[N];
	for(int i=0;i<=2*d;i++) tp[i]=0;
	for(int i=0;i<d;i++)
		for(int j=0;j<d;j++)
			tp[i+j]=add(tp[i+j],mul(a[i],b[j]));
	for(int i=2*d;i>=d;i--) if(tp[i]) {
		for(int j=1;j<=d;j++)
			tp[i-j]=add(tp[i-j],mul(tp[i],g[j]));
		tp[i]=0;
	}
	for(int i=0;i<d;i++) a[i]=tp[i];
}
int main() {
	cin>>k>>n; --k; d=deg[k];
	for(int i=0;i<=d;i++) g[i]=poly[k][i];
	f[1]=1; h[0]=1;
	for(n--;n;n>>=1,mul(f,f))
		if(n&1) mul(h,f);
	int ans=0;
	for(int i=0;i<d;i++)
		ans=add(ans,mul(h[i],init[k][i+1]));
	cout<<ans<<'\n';
}

猜你喜欢

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