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

Tiling

Time Limit: 1000ms
Memory Limit: 32768KB
This problem will be judged on FZU. Original ID:  2040
64-bit integer IO format:  %I64d      Java class name:  Main
Prev  Submit  Status  Statistics  Discuss  Next
Font Size:  +  -
Type:   None Graph Theory     2-SAT     Articulation/Bridge/Biconnected Component     Cycles/Topological Sorting/Strongly Connected Component     Shortest Path         Bellman Ford         Dijkstra/Floyd Warshall     Euler Trail/Circuit     Heavy-Light Decomposition     Minimum Spanning Tree     Stable Marriage Problem     Trees     Directed Minimum Spanning Tree     Flow/Matching         Graph Matching             Bipartite Matching             Hopcroft–Karp Bipartite Matching             Weighted Bipartite Matching/Hungarian Algorithm         Flow             Max Flow/Min Cut             Min Cost Max Flow DFS-like     Backtracking with Pruning/Branch and Bound     Basic Recursion     IDA* Search     Parsing/Grammar     Breadth First Search/Depth First Search     Advanced Search Techniques         Binary Search/Bisection         Ternary Search Geometry     Basic Geometry     Computational Geometry     Convex Hull     Pick's Theorem Game Theory     Green Hackenbush/Colon Principle/Fusion Principle     Nim     Sprague-Grundy Number Matrix     Gaussian Elimination     Matrix Exponentiation Data Structures     Basic Data Structures     Binary Indexed Tree     Binary Search Tree     Hashing     Orthogonal Range Search     Range Minimum Query/Lowest Common Ancestor     Segment Tree/Interval Tree     Trie Tree     Sorting     Disjoint Set String     Aho Corasick     Knuth-Morris-Pratt     Suffix Array/Suffix Tree Math     Basic Math     Big Integer Arithmetic     Number Theory         Chinese Remainder Theorem         Extended Euclid         Inclusion/Exclusion         Modular Arithmetic     Combinatorics         Group Theory/Burnside's lemma         Counting     Probability/Expected Value Others     Tricky     Hardest     Unusual     Brute Force     Implementation     Constructive Algorithms     Two Pointer     Bitmask     Beginner     Discrete Logarithm/Shank's Baby-step Giant-step Algorithm     Greedy     Divide and Conquer Dynamic Programming                     Tag it!
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;
	}
}


0
0

你可能感兴趣的:(struct,Integer,search,input,each,Numbers)