2011年全国大学生程序设计邀请赛(福州)——Tiling

本文讨论了如何利用矩阵乘法解决Tiling问题,包括构建转移矩阵、快速幂运算以及通过模运算输出答案的方法。
部署运行你感兴趣的模型镜像

Tiling

1000ms
32768KB
This problem will be judged on FZU. Original ID:  2040
64-bit integer IO format:  %I64d      Java class name:  Main
Font Size:   
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                    
  • We can perfectly tile one m*n rectangle by any size of tiles. The following picture shows all the 34 possible ways to perfectly title a 3*2 rectangle.
    Now you are given one m*n rectangle, your task is to calculate the total number of the ways to perfectly title the given rectangle. Please mod the answer with 1,000,000,007 when you output it.

    Input

    The first line of the input contains an integer T(T≤100), indicating the number of test cases. Following is T lines, each containing two integer numbers m(1≤m≤6) and n(1≤n≤1,000,000,000).

    Output

    For each test case, print a line containing the test case number (beginning with 1) and the answer.

    Sample Input

    2
    2 2
    3 2
    

    Sample Output

    Case 1: 8
    Case 2: 34



    矩阵乘法,借用bianchengla的模板

    矩阵表示最后两行的状态转移,即上一行的某个状态可以通过几种方式转移到最后一行的状态,构成一个矩阵。由于每一行最多六个格子,状态只需要考虑5个分割线是否存在,所以最大是32*32。如果上一行某两个位置有分割线,下一行相同的两个位置也有,(且中间没有其他的隔断),那么此处有两种可能,即上下联通或者不联通,结果mat[i][j]*2,上代码:

    #include <iostream>
    #include <cstdio>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int maxn = 1 << 5;
    const LL MOD = 1000000007;
    
    struct mat {
        int n;
        LL data[maxn][maxn];
        friend mat operator * (const mat& a, const mat& b) {
            mat r;
            r.n = a.n;
            for (int i = 0; i < r.n; ++i) {
                for (int j = 0; j < r.n; ++j) {
                    r.data[i][j] = 0;
                    for (int k = 0; k < r.n; ++k) {
                        r.data[i][j] += a.data[i][k] * b.data[k][j] % MOD;
                    }
                    r.data[i][j] %= MOD;
                }
            }
            return r;
        }
        friend mat pow(mat a, int b) {
            mat r; r.n = a.n;
            for (int i = 0; i < r.n; ++i) {
                for (int j = 0; j < r.n; ++j) {
                    r.data[i][j] = 0;
                }
                r.data[i][i] = 1;
            }
            for (;b;) {
                if ( b & 1 ) r = r * a;
                if ( b >>= 1 ) a = a * a;
            }
            return r;
        }
    } ;
    //上面是bianchengla的矩阵乘法和快速幂模板
    ///////////////////////////////////////////////////////////
    
    mat m[6];
    void buildmat(int n){
    	m[n].n = 1<<n;
    	for(int x=0; x<(1<<n); x++){
    		for(int y=0; y<(1<<n); y++){	//填充x到y的状态转移方式
    			//
    			m[n].data[x][y] = 1;
    
    			int t[8] = {0};
    			for(int i=0; i<n; i++){
    				if( x&(1<<i) )  t[i+1] ++;
    				if( y&(1<<i) )  t[i+1] ++;
    			}
    			t[0] = 2; t[n+1] = 2;		//t[]存储两行中这个位置有几条分割线,头尾要各补充一条
    			int re = 0;
    			for(int i=0; i<=n+1; i++){
    				if(t[i]==2)  re++;		//==2就+1
    				if(t[i]==1)  re=0;		//==1就中断了
    				if(re==2)  m[n].data[x][y] *= 2, re=1;	//凑齐两个就×2,re变成1
    			}
    		}
    	}
    }
    
    int main()
    {
    	for(int ii=0; ii<6; ii++)
    		buildmat(ii);		// built mat in m[i]
    
    	int T; scanf("%d", &T);
    	int r, n;
    
    	for(int ti=1; ti<=T; ti++){
    		scanf("%d%d", &r, &n);
    		mat res = pow(m[r-1], n-1);		//我的习惯所有的数组都从0处开始储存,所以这儿会出现-1
    		LL sum = 0;
    		for(int i=0; i<res.n; i++)
    			for(int j=0; j<res.n; j++)
    				sum = (sum+res.data[i][j]) % MOD;
    		cout << "Case " << ti << ": " << (sum%MOD) << endl;
    	}
    }
    


    您可能感兴趣的与本文相关的镜像

    Linly-Talker

    Linly-Talker

    AI应用

    Linly-Talker是一款创新的数字人对话系统,它融合了最新的人工智能技术,包括大型语言模型(LLM)、自动语音识别(ASR)、文本到语音转换(TTS)和语音克隆技术

    在IT领域,Tiling(分块)是一种重要的技术手段,以下是关于它的详细介绍: ### 基本概念 Tiling是将一个较大的对象(如数据、图像、矩阵等)划分成若干个小块(Tile),分别对这些小块进行处理,最后再将处理结果进行拼接的方法。以图像分块为例,就是把一幅完整的图像分割成多个小的图像块,分别处理后再组合成完整图像[^1]。 ### 应用场景 - **图像处理**:在处理大尺寸图像时,由于内存限制无法一次性加载整个图像。通过图像分块技术,每次只处理一个小块,减少内存占用。同时,多个块可以并行处理,提升处理速度。此外,还可通过设置重叠区域减少边界效应[^1]。 ```python import cv2 # 读取大图像 image = cv2.imread('large_image.jpg') # 定义分块大小 tile_size = (200, 200) # 分块处理 for y in range(0, image.shape[0], tile_size[1]): for x in range(0, image.shape[1], tile_size[0]): tile = image[y:y + tile_size[1], x:x + tile_size[0]] # 对每个小块进行处理,例如灰度化 gray_tile = cv2.cvtColor(tile, cv2.COLOR_BGR2GRAY) # 这里可以进行更复杂的处理 ``` - **计算机图形学**:在3D渲染中,对于大型场景的渲染,可将场景划分成多个小块进行渲染,提高渲染效率。同时,在纹理映射时,也可采用分块技术,减少内存开销。 - **数据处理与分析**:在处理大规模数据集时,将数据分块可以提高数据处理的并行性。例如,在矩阵运算中,将大矩阵分块后进行乘法运算,可充分利用多核处理器的并行计算能力。 ### 优势 - **内存优化**:每次只处理一个小块,减少了对内存的占用。对于资源受限的系统,这一优势尤为明显[^1]。 - **并行加速**:多个块可以并行处理,充分利用多核处理器的计算能力,提升处理速度。在分布式计算环境中,不同的节点可以同时处理不同的块,进一步提高处理效率[^1]。 - **边界处理**:通过设置重叠区域,可以减少边界效应的影响。在图像处理中,重叠区域可以使相邻块之间的过渡更加自然[^1]。 ### 挑战 - **块间一致性**:在分块处理过程中,需要确保各个块的处理结果在拼接时能够保持一致性。例如,在图像处理中,相邻块的颜色、亮度等属性需要进行适当的调整,以避免拼接处出现明显的接缝。 - **通信开销**:在并行处理多个块时,需要考虑块之间的通信开销。如果通信开销过大,可能会抵消并行处理带来的性能提升。
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值