ASC(1)E(矩阵快速幂+简单DP)

Nice Patterns Strike Back

Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
Problem Description

      You might have noticed that there is the new fashion among rich people to have their yards tiled with black and white tiles, forming a pattern. The company Broken Tiles is well known as the best tiling company in our region. It provides the widest choices of nice patterns to tile your yard with. The pattern is nice if there is no square of size 2 × 2, such that all tiles in it have the same color. So patterns on the figure 1 are nice, while patterns on the figure 2 are not.

      The president of the company wonders whether the variety of nice patterns he can provide to the clients is large enough. Thus he asks you to find out the number of nice patterns that can be used to tile the yard of size N × M . Now he is interested in the long term estimation, so he suggests N ≤ 10100However, he does not like big numbers, so he asks you to find the answer modulo P .

Input
      The input file contains three integer numbers: N (1 ≤ N ≤ 10 100), M (1 ≤ M ≤ 5) and P (1 ≤ P ≤10000).
Output
      Write the number of nice patterns of size N × M modulo P to the output file.
Sample Input
2 2 5
3 3 23
Sample Output
4
0

题意:RT

思路:用dp[i]表示前i行所有方案数,那么可以从dp[i]转移到dp[i+1],这个只需要累加第i和第i+1行满足的情况即可

            但是n很大,所以是不可能for一遍n来求的

            不难发现,每次的转移都是一样的,即只需要判断相邻2行的满足情况即可

            由于m<=5,可以用状态压缩来表示相邻两行格子的状态,1代表黑,0代表白,构造一个矩阵M[i][j]

            如果M[i][j]=1代表上一行的状态i和当前行的状态j是满足的

            所以有dp[i]=( M^(i-1) )*dp[1],其中dp[1]=(1<<m)代表所有的方案都满足

            而M^(i-1)可以用经典的矩阵快速幂来求得

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          using namespace std; const int MAXN = 33; int A[MAXN][MAXN]; int dp[MAXN][1]; char s[110]; int ans; int p; int sz; int mx; int add(int x,int y) { x+=y; if(x>=p)x-=p; return x; } vector 
          
          
            > m_pow(vector 
           
             n) { sz++; int cnt=0,i,j,k; int L=n.size(); vector 
             
             
               >ans,C; int cn=0; for(i=0;i 
              
                q1; vector 
               
                 q2; ans.push_back(q1); C.push_back(q2); for(j=0;j 
                
                  t,t2; for(i=0;i 
                 
                   >temp=m_pow(t2); for(i=0;i 
                  
                    q; int L=strlen(s); for(int i=L-1;i>=0;i--){ if(s[i]!='0'){ s[i]=s[i]-1; for(int j=i+1;j 
                   
                     >ans=m_pow(q); for(int i=0;i 
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值