zoukankan      html  css  js  c++  java
  • CSP-201409

      前三题代码并未保存。

     

     

     

    问题描述

    试题编号: 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 }

    -

     

     

  • 相关阅读:
    github上十二款最著名的Android播放器开源项目
    ReactiveX/RxJava文档中文版
    腾讯开源的Android UI框架——QMUI Android
    android EventBus的简单使用
    android EventBus的简单使用
    MVP实战心得—封装Retrofit2.0+RxAndroid+RxBus
    动态合并Repeater控件数据列
    动态合并GridView数据行DataRow的列
    找出1至10范围奇数
    判断某元素是否在Array中
  • 原文地址:https://www.cnblogs.com/zzqc/p/12149818.html
Copyright © 2011-2022 走看看