记录编号 88442 评测结果 AAAAAAA
题目名称 [UVa 11276] 神奇的七 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 4.218 s
提交时间 2014-02-20 22:21:20 内存使用 0.32 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<cmath>
using namespace std;
//本题下标从0开始
typedef unsigned long long ll;
const int SIZES=130;
const ll MOD=10000;
int getdig(int s,int k){
	return (s>>(k<<1))&3;
}
void printdig(int s){//调试接口,输出s的二进制
	for(int i=0;i<8;i++) cout<<getdig(s,i);
}
int changedig(int s,int k,int t){
	int temp=(k<<1);
	s&=~(3<<temp);
	return s|(t<<temp);
}
vector<int> ham_st;//插头DP(7格)的状态集合
class MATRIX{
public:
	int n,m;
	vector<pair<pair<int,int>,int> > val;
	int fr[SIZES];
	void print(void){//调试接口,输出矩阵
		cout<<"size:"<<n<<" "<<m<<endl;
		for(int i=0;i<val.size();i++) cout<<val[i].first.first<<" "<<val[i].first.second<<" : "<<val[i].second<<endl;
	}
	void clear(int x,int y){
		n=x,m=y;
		val.clear();
		memset(fr,-1,sizeof(fr));
	}
	void assign_one(int x){
		n=m=x;
		for(int i=0;i<x;i++){
			val.push_back(make_pair(make_pair(i,i),1));
			fr[i]=i;
		}
	}
	void assign_array(ll atp[SIZES][SIZES]){
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(atp[i][j]){
					atp[i][j]%=MOD;
					val.push_back(make_pair(make_pair(i,j),atp[i][j]));
					if(fr[i]==-1) fr[i]=val.size()-1;
				}
			}
		}
	}
	int value(int p,int q){
		for(int i=0;i<val.size();i++){
			if(val[i].first.first==p&&val[i].first.second==q) return val[i].second;
		}
		return 0;
	}
};
MATRIX operator * (MATRIX &a,MATRIX &b){
	MATRIX ans;
	ans.clear(a.n,b.m);
	ll atp[SIZES][SIZES]={0};
	int p,q,r,v1,v2;
	for(int i=0;i<a.val.size();i++){
		p=a.val[i].first.first,q=a.val[i].first.second,v1=a.val[i].second;
		for(int j=b.fr[q];j<b.val.size()&&b.val[j].first.first==q;j++){
			r=b.val[j].first.second,v2=b.val[j].second;
			atp[p][r]+=v1*v2;
		}
	}
	ans.assign_array(atp);
	return ans;
}
MATRIX D_DOM,D_HAMMT,D_HAMSM,D_HAMSF;//转移矩阵:多米诺骨牌,多回路,单回路的中间,单回路的最后一列
MATRIX ORI_DOM,ORI_HAMM,ORI_HAMS;//初始矩阵:多米诺骨牌,多回路,单回路
MATRIX quickpow(MATRIX a,ll n){
	MATRIX ans;
	ans.assign_one(a.n);
	while(n){
		if(n&1) ans=ans*a;
		a=a*a;
		n>>=1;
	}
	return ans;
}
void DOM_DFS(ll s[SIZES][SIZES],int s1,int s2,int p){
	if(p>7) return;
	if(p==7){
		s[s1][s2]++;
		return;
	}
	DOM_DFS(s,s1*2,s2*2+1,p+1);//这一格不放
	DOM_DFS(s,s1*2+1,s2*2,p+1);//竖着放
	DOM_DFS(s,s1*4+3,s2*4+3,p+2);//横着放
}
int rightmatch(int s,int k){//与s的第k位匹配的右插头
	int dta=1,temp;
	while(k<8){
		k++;
		temp=getdig(s,k);
		if(temp==1) dta++;
		else if(temp==2) dta--;
		if(dta==0) return k;
	}
	cout<<"bracket match error!"<<endl;
	return -1;
}
int leftmatch(int s,int k){
	int dta=-1,temp;
	while(k>=0){
		k--;
		temp=getdig(s,k);
		if(temp==1) dta++;
		else if(temp==2) dta--;
		if(dta==0) return k;
	}
	cout<<"bracket match error!"<<endl;
	return -1;
}
bool plug_exi(int x,int type,int dir){
	//2下4右
	if(dir==2){
		return x<6;
	}
	if(dir==4){
		return (type==0||type==1);
	}
	cout<<"plug check error!";
	return 0;
}
void HAM_DFS(ll s[SIZES][SIZES],int pos,int now,int x,int type){//最开始的那个状态是ham_st[pos],现在到了now,该放第x行
	//type=0:多回路,type=1:单回路的中间,type=2:单回路的最后一列
	if(x==7){
		if(getdig(now,7)==0){
			int nowpos=lower_bound(ham_st.begin(),ham_st.end(),now)-ham_st.begin();
			s[pos][nowpos]++;
			s[pos][nowpos]%=MOD;
		}
		return;
	}
	int p=getdig(now,x),q=getdig(now,x+1),next;
	if(!p&&!q){//两个都是0
		if(plug_exi(x,type,2)&&plug_exi(x,type,4)){//有下插头和右插头
			next=now;
			next=changedig(next,x,1),next=changedig(next,x+1,2);//有下插头和右插头,二者匹配
			HAM_DFS(s,pos,next,x+1,type);
		}
	}
	else if(!(p&&q)&&(p||q)){//一个是0一个不是0
		if(plug_exi(x,type,2)){//下
			next=now;
			next=changedig(next,x,0),next=changedig(next,x+1,p+q);
			HAM_DFS(s,pos,next,x+1,type);
		}
		if(plug_exi(x,type,4)){//右
			next=now;
			next=changedig(next,x,p+q),next=changedig(next,x+1,0);
			HAM_DFS(s,pos,next,x+1,type);
		}
	}
	else if(p==1&&q==1){
		next=changedig(now,rightmatch(now,x+1),1);
		next=changedig(next,x,0),next=changedig(next,x+1,0);
		HAM_DFS(s,pos,next,x+1,type);
	}
	else if(p==2&&q==2){
		next=changedig(now,leftmatch(now,x),2);
		next=changedig(next,x,0),next=changedig(next,x+1,0);
		HAM_DFS(s,pos,next,x+1,type);
	}
	else if(p==2&&q==1){
		next=now;
		next=changedig(next,x,0),next=changedig(next,x+1,0);
		HAM_DFS(s,pos,next,x+1,type);
	}
	else if(p==1&&q==2){
		if(type==0||(type==2&&x==6)){
			next=now;
			next=changedig(next,x,0),next=changedig(next,x+1,0);
			HAM_DFS(s,pos,next,x+1,type);
		}
	}
}
void HAM_prepare(MATRIX &D,int type){
	ll atp[SIZES][SIZES]={0};
	D.clear(ham_st.size(),ham_st.size());
	for(int i=0;i<ham_st.size();i++){
		HAM_DFS(atp,i,ham_st[i]<<2,0,type);
	}
	D.assign_array(atp);
}
void HAM_searchST(int s,int left,int right,int p){
	if(p==7){
		if(left==right) ham_st.push_back(s);
		return;
	}
	HAM_searchST(s<<2,left,right,p+1);//空
	if(left<right) HAM_searchST((s<<2)+1,left+1,right,p+1);//左
	HAM_searchST((s<<2)+2,left,right+1,p+1);//右
}
void prepare(void){
	ll atp[SIZES][SIZES]={0};
	HAM_searchST(0,0,0,0);
	D_DOM.clear(128,128);
	DOM_DFS(atp,0,0,0);
	D_DOM.assign_array(atp);
	HAM_prepare(D_HAMMT,0);
	HAM_prepare(D_HAMSM,1);
	HAM_prepare(D_HAMSF,2);
	memset(atp,0,sizeof(atp));
	ORI_DOM.clear(1,128);
	atp[0][127]=1;
	ORI_DOM.assign_array(atp);
	memset(atp,0,sizeof(atp));
	ORI_HAMM.clear(1,ham_st.size());
	atp[0][0]=1;
	ORI_HAMM.assign_array(atp);
	memset(atp,0,sizeof(atp));
	ORI_HAMS.clear(1,ham_st.size());
	atp[0][0]=1;
	ORI_HAMS.assign_array(atp);
}
void answer(ll n){
	if(n&1){
		printf("0000\n");
		return;
	}
	MATRIX A=ORI_DOM,B=ORI_HAMM,C=ORI_HAMS;
	MATRIX tpa=quickpow(D_DOM,n),tpb=quickpow(D_HAMMT,n),tpc=quickpow(D_HAMSM,n-1);
	A=A*tpa;B=B*tpb;C=C*tpc;C=C*D_HAMSF;
	int ans=0;
	ans+=A.value(0,127),ans+=B.value(0,0),ans+=C.value(0,0);
	ans%=MOD;
	printf("%04d\n",ans);
}
int main(){
	freopen("magicalseven.in","r",stdin);
	freopen("magicalseven.out","w",stdout);
	prepare();
	ll n;
	while(scanf("%llu",&n)!=EOF) answer(n);
	return 0;
}