前三题代码并未保存。
问题描述
试题编号: | 201409-5 |
试题名称: |
拼图(100/100) |
时间限制: | 3.0s |
内存限制: | 256.0MB |
问题描述: |
问题描述
给出一个n×m的方格图,现在要用如下L型的积木拼到这个图中,使得方格图正好被拼满,请问总共有多少种拼法。其中,方格图的每一个方格正好能放积木中的一块。积木可以任意旋转。
输入格式
输入的第一行包含两个整数n, m,表示方格图的大小。
输出格式
输出一行,表示可以放的方案数,由于方案数可能很多,所以请输出方案数除以1,000,000,007的余数。
样例输入
6 2
样例输出
4
样例说明
四种拼法如下图所示:
评测用例规模与约定
在评测时将使用10个评测用例对你的程序进行评测。
评测用例1和2满足:1<=n<=30,m=2。 评测用例3和4满足:1<=n, m<=6。 评测用例5满足:1<=n<=100,1<=m<=6。 评测用例6和7满足:1<=n<=1000,1<=m<=6。 评测用例8、9和10满足:1<=n<=10^15,1<=m<=7。 |
直接轮廓线可以拿到70.
正解应该是矩阵幂,但暂时没想到如何推导矩阵a[S1][S2]表示上一行S1->当前行S2转移。
正解在下方
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define LL long long 5 #define inf 0x3f3f3f3f 6 #define pii pair<int,int> 7 #define pb push_back 8 #define all(v) (v.begin(),v.end()) 9 #define mp make_pair 10 const LL mod=1000000007; 11 LL f[2][(1<<8)+5]; 12 LL n,m; 13 int biti(int k,int i){ 14 return ((k>>i)&1); 15 } 16 int main() 17 { 18 cin>>n>>m; 19 int cur=0,all=(1<<(m+1)); 20 f[cur][0]=1; 21 for(int i=1;i<=n;++i){ 22 for(int j=1;j<=m;++j){ 23 cur^=1; 24 memset(f[cur],0,sizeof(f[cur])); 25 for(int k=0;k<all;++k){ 26 27 if(i==1||(i==2&&j==1)||biti(k,m)) 28 (f[cur][(k<<1)&(all-1)]+=f[cur^1][k])%=mod; 29 if(i!=1 && j!=1 ){ 30 if(biti(k,0)==0 && biti(k,m)==0){ 31 (f[cur][(k<<1)|3]+=f[cur^1][k])%=mod; 32 } 33 if(biti(k,0)==0 && biti(k,m-1)==0 && biti(k,m)==1){ 34 (f[cur][(k<<1)&(all-1)|3|(1<<m)]+=f[cur^1][k])%=mod; 35 } 36 if(biti(k,m)==0 && biti(k,m-1)==0){ 37 (f[cur][(k<<1)|1|(1<<m)]+=f[cur^1][k])%=mod; 38 } 39 } 40 if(i!=1 && j!=m && ( biti(k,m)==1 ||i==2&&j==1) &&biti(k,m-1)==0 && biti(k,m-2)==0){ 41 (f[cur][(k<<1)&(all-1)|1|(3<<(m-1))]+=f[cur^1][k])%=mod; 42 } 43 44 } 45 } 46 } 47 cout<<f[cur][all-1]<<endl; 48 return 0; 49 }
正解为矩阵快速幂:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define LL long long 5 #define inf 0x3f3f3f3f 6 #define pii pair<int,int> 7 #define pb push_back 8 #define all(v) (v.begin(),v.end()) 9 #define mp make_pair 10 11 12 const LL mod=1000000007; 13 int biti(int n,int i){return ((n>>i)&1) ;} 14 LL all,N,M; 15 LL a[(1<<7)][(1<<7)],res[(1<<7)][(1<<7)],temp[(1<<7)][(1<<7)]; 16 void dfs(int S1,int S,int S2){ 17 if(S==all){ 18 a[S1][S2]++; 19 return; 20 } 21 for(int i=0;i<M;++i){ 22 if(biti(S,i))continue; 23 if(i<M-1&&!biti(S2,i)&&!biti(S2,i+1))dfs(S1,(S|(1<<i)),(S2|(3<<i))); 24 if(i>0&&!biti(S2,i)&&!biti(S2,i-1))dfs(S1,(S|(1<<i)),(S2|(3<<(i-1)))); 25 26 if(i<M-1&&!biti(S,i+1)&&!biti(S2,i))dfs(S1,(S|(3<<i)),(S2|(1<<i))); 27 if(i<M-1&&!biti(S,i+1)&&!biti(S2,i+1))dfs(S1,(S|(3<<i)),(S2|(1<<(i+1)))); 28 break;//这里的break很关键,否则会算重 29 } 30 } 31 void mul(LL a[][(1<<7)],LL b[][(1<<7)],int sz=(1<<M)){// a<-a*b 32 for(int i=0;i<sz;++i){ 33 for(int j=0;j<sz;++j){ temp[i][j]=0; 34 for(int k=0;k<sz;++k){ 35 temp[i][j]=(temp[i][j]+a[i][k]*b[k][j])%mod; 36 } 37 } 38 } 39 for(int i=0;i<sz;++i) 40 for(int j=0;j<sz;++j)a[i][j]=temp[i][j]; 41 } 42 void qpow(){ 43 LL n=N; 44 for(int i=0;i<=all;++i)res[i][i]=1; 45 while(n){ 46 if(n&1)mul(res,a); 47 n>>=1; 48 mul(a,a); 49 } 50 } 51 int main() 52 { 53 cin>>N>>M; 54 all=(1<<M)-1; 55 for(int i=0;i<=all;++i)dfs(i,i,0); 56 qpow(); 57 cout<<res[all][all]<<endl;//f(0,all)=1,f(n)=f(0)*aN 58 return 0; 59 }
-