记录编号 88162 评测结果 AAAAAAAAAA
题目名称 [UVa 11741] 网格覆盖 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 2.981 s
提交时间 2014-02-17 20:18:00 内存使用 0.32 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
//本题下标从0开始
ll MOD=10000007;
const int SIZES=16,SIZER=4;
int R,C,N;
vector<pair<int,int> > unusable;//first是列坐标,second是行坐标
void printdig(int x){//调试接口,以二进制形式输出x
	for(int i=R-1;i>=0;i--){cout<<((x>>i)&1);}
}
class MATRIX{
public:
	int n,m;
	ll s[SIZES][SIZES];
	void clear(int x,int y){
		n=x,m=y;
		memset(s,0,sizeof(s));
	}
	void assign_one(int x){
		clear(x,x);
		for(int i=0;i<x;i++) s[i][i]=1;
	}
	void print(void){//调试接口,输出转移矩阵的情况
		cout<<"size:"<<n<<" "<<m<<endl;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){if(s[i][j]==0){continue;}printdig(i);cout<<" ";printdig(j);cout<<" :"<<s[i][j]<<endl;}
		}
	}
};
inline MATRIX operator * (MATRIX &a,MATRIX &b){
	MATRIX ans;
	ans.clear(a.n,b.m);
	for(int i=0;i<a.n;i++){
		for(int j=0;j<b.m;j++){
			for(int k=0;k<a.m;k++){
				ans.s[i][j]+=(a.s[i][k]*b.s[k][j])%MOD;
				//ans.s[i][j]%=MOD;
			}
			ans.s[i][j]%=MOD;
		}
	}
	return ans;
}
inline MATRIX quickpow(MATRIX a,int n){
	MATRIX ans;
	ans.assign_one(a.n);
	while(n){
		if(n&1) ans=ans*a;
		a=a*a;
		n>>=1;
	}
	return ans;
}
MATRIX nD;//全白列的转移矩阵
vector<pair<int,MATRIX> > cD;//第first列的转移矩阵
bool cv[SIZER];
void DFS(MATRIX &D,int s1,int s2,int p){
	if(p>R) return;
	if(p==R){
		D.s[s1][s2]++;
		return;
	}
	if(cv[p]){
		DFS(D,s1*2+1,s2*2+1,p+1);
		return;
	}
	DFS(D,s1*2,s2*2+1,p+1);//这一格不放
	DFS(D,s1*2+1,s2*2,p+1);//竖着放
	if(p<R-1&&!cv[p+1]) DFS(D,s1*4+3,s2*4+3,p+2);//横着放
}
void prepare(void){
	int i=0,j,k;
	MATRIX nowd;
	nD.clear(1<<R,1<<R);
	memset(cv,0,sizeof(cv));
	DFS(nD,0,0,0);
	while(i<unusable.size()){
		j=i+1;
		while(j<unusable.size()&&unusable[j].first==unusable[i].first) j++;
		memset(cv,0,sizeof(cv));
		nowd.clear(1<<R,1<<R);
		for(k=i;k<j;k++) cv[unusable[k].second]=true;
		DFS(nowd,0,0,0);
		cD.push_back(make_pair(unusable[i].first,nowd));
		i=j;
	}
}
int kase=0;
void work(){
	prepare();
	MATRIX ori;
	ori.clear(1,1<<R);
	ori.s[0][(1<<R)-1]=1;
	int tot=-1;
	MATRIX temp;
	for(int i=0;i<cD.size();i++){
		if(cD[i].first-1-tot>0){
			temp=quickpow(nD,cD[i].first-1-tot);
			ori=ori*temp;
		}
		ori=ori*cD[i].second;
		tot=cD[i].first;
	}
	if(C-1-tot>0){
		temp=quickpow(nD,C-1-tot);
		ori=ori*temp;
	}
	printf("Case %d: %lld\n",++kase,ori.s[0][(1<<R)-1]);
}
bool init(void){
	unusable.clear();
	cD.clear();
	scanf("%d%d%d",&R,&C,&N);
	if(!R&&!C&&!N) return false;
	int x,y;
	for(int i=1;i<=N;i++){
		scanf("%d%d",&x,&y);
		unusable.push_back(make_pair(y,x));
	}
	sort(unusable.begin(),unusable.end());
	return true;
}
int main(){
	freopen("ignoretheblocks.in","r",stdin);
	freopen("ignoretheblocks.out","w",stdout);
	while(init()) work();
	return 0;
}