记录编号 131531 评测结果 AAAAAAAAAA
题目名称 [NOI 2007]生成树计数 最终得分 100
用户昵称 Gravatar天一阁 是否通过 通过
代码语言 C++ 运行时间 0.204 s
提交时间 2014-10-24 16:57:20 内存使用 0.37 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define Mod 65521
#define int64 long long
using namespace std;
int K,Num,fa[52]={0};
int64 N;
vector<int> step;
class Matrix{
	public:
	int64 ele[61][61];
	int n,m;
	void empty(int N,bool zero){n=N;m=N;if(!zero)for(int i=1;i<=n;i++) ele[i][i]=1;}
	Matrix(){memset(ele,0,sizeof(ele));n=0;m=0;}
	Matrix operator*(const Matrix &a){
		Matrix c; c.n=n; c.m=a.m;
		for(int i=1;i<=c.n;i++)
			for(int j=1;j<=c.m;j++)
				for(int k=1;k<=a.m;k++)
					(c.ele[i][j]+=ele[i][k]*a.ele[k][j])%=Mod;
		return c;
	}
}M,D;
int get_num(int w,int t){return (w>>(3*t))&7;}
int change_num(int w,int t,int i){return (w&(~(7<<(3*t))))|(i<<(3*t));}
int find(int* fa,int x){return fa[x]?fa[x]=find(fa,fa[x]):x;}
void packback(int* fa,int k,int w){
	int tp[52]={0};
	for(int i=1;i<=k;i++){
		int t=get_num(w,i);
		if(!tp[t]) tp[t]=i,fa[i]=0; else fa[i]=tp[t];
	}
}
int expand_num(int* fa,int k){
	int tp[52]={0},res=0,color=0;
	for(int i=1;i<=k;i++){
		int t=find(fa,i);
		if(!tp[t]) tp[i]=tp[t]=++color; else tp[i]=tp[t];
	}
	for(int i=1;i<=k;i++) res=change_num(res,i,tp[i]);
	return res;
}
Matrix pow(Matrix a,int64 n){
	Matrix res; res.empty(Num,false);
	for(;n;n>>=1,a=a*a) if(n&1) res=res*a;
	return res;
}
void dfs(int t,int cnt,int w){
	if(t==K) step.push_back(w);
	else{
		for(int i=1;i<=cnt;i++) dfs(t+1,cnt,change_num(w,t+1,i));
		dfs(t+1,cnt+1,change_num(w,t+1,cnt+1));
	}
}
bool check(int* fa,int k,int pos){
	for(int i=1;i<=k;i++){
		if(pos&(1<<(i-1))){
			int t=find(fa,i);
			if(t==find(fa,k+1)) return false; else fa[find(fa,k+1)]=t;
		}
	}return true;
}
void calc_M(int t,int w){
	if(t==K) M.ele[1][lower_bound(step.begin(),step.end(),w)-step.begin()+1]++;
	else{
		int tp[52]={0};packback(tp,t,w);
		for(int i=0;i<(1<<t);i++){
			memmove(fa,tp,sizeof(tp));
			if(check(fa,t,i)) calc_M(t+1,expand_num(fa,t+1));
		}
	}
}
void calc_D(){
	int tp[52];
	for(int i=1;i<=Num;i++){
		int tmp=step[i-1]; packback(tp,K,tmp);
		for(int j=0;j<(1<<K);j++){
			memmove(fa,tp,sizeof(tp));
			if(check(fa,K,j)){
				bool flag=false;
				for(int k=2;k<=K+1;k++){
					if(find(fa,1)==find(fa,k)){
						int t=fa[1];
						for(int l=2;l<=K+1;l++){
							if(fa[l]==1) fa[l-1]=K+1;
							else if(fa[l]>0) fa[l-1]=fa[l]-1;
							else fa[l-1]=0;
						}
						if(t>0) fa[K+1]=t-1; else fa[K+1]=0;
						D.ele[i][lower_bound(step.begin(),step.end(),expand_num(fa,K))-step.begin()+1]++;
						break;
					}
				}
			}
		}
	}
}
int main(){
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	cin>>K>>N;
	step.clear(); dfs(0,0,0);
	sort(step.begin(),step.end());
	Num=step.size();
	M.n=1; M.m=Num; D.n=Num; D.m=Num;
	calc_M(0,0); calc_D();
	M=M*pow(D,N-K);
	cout<<M.ele[1][1]<<endl;
}