某考试 T1 line

 

 

 

状压dp+矩阵转移,据说正解是dfs出的合法状态,,但难道不是三个for就行了吗2333

 

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define ll long long
const int ha=1000000007;
using namespace std;
int C[12][12],n,P,Q,cnt;
struct node{
	int a[3],full;
}zt[233];

inline int add(int x,int y){
	x+=y;
	return x>=ha?x-ha:x;
}

struct matrix{
	int a[199][199];
	
	inline void clear(){
		memset(a,0,sizeof(a));
	}
	
	matrix operator *(const matrix &u)const{
		matrix r;
		r.clear();
		for(int k=1;k<=cnt;k++)
		    for(int i=1;i<=cnt;i++)
		        for(int j=1;j<=cnt;j++) r.a[i][j]=add(r.a[i][j],a[i][k]*(ll)u.a[k][j]%ha);
		
		return r;
	}
}base,ANS;

inline void init(){
	C[0][0]=1;
	for(int i=1;i<=8;i++){
	    C[i][0]=1;
	    for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]);
	}
}

inline void can(int i,int j){
	node x=zt[i],y=zt[j];
	if(y.a[1]<=x.a[0]&&y.a[2]<=x.a[1]&&x.full+(y.a[1]+y.a[2]==n?1:0)==y.full){
		base.a[i][j]=C[x.a[0]][y.a[1]]*(ll)C[x.a[1]][y.a[2]]%ha;
	}
}

inline void build(){
	for(int i=n;i>=0;i--)
	    for(int j=(P==2?0:n-i);j>=0;j--)
	            for(int l=0;l<=Q;l++) zt[++cnt]=(node){i,n-i-j,j,l};
	
	base.clear();
	for(int i=1;i<=cnt;i++)
	    for(int j=1;j<=cnt;j++) can(i,j);
}

inline void solve(ll y){
	ANS.clear();
	for(int i=1;i<=cnt;i++) ANS.a[i][i]=1;
	int ans=0;
	for(;y;y>>=1,base=base*base) if(y&1) ANS=ANS*base;
	/*
	for(int i=1;i<=cnt;i++){
		for(int j=1;j<=cnt;j++) printf("%d ",ANS.a[i][j]);
		puts("");
	}
	*/
	for(int i=1;i<=cnt;i++) ans=add(ans,ANS.a[1][i]);
	printf("%d\n",ans);
}

int main(){
//	freopen("line.in","r",stdin);
//	freopen("line.out","w",stdout);
	
	init();
	ll m;
	scanf("%d%lld%d%d",&n,&m,&P,&Q);
	if(P==1){
		puts("1");
		return 0;
	}
	
	build();
	solve(m);
	
	return 0;
}

  

posted @ 2018-03-17 15:41  蒟蒻JHY  阅读(198)  评论(0编辑  收藏  举报