• POJ3420 Quad Tiling DP + 矩阵高速幂


            题目大意是用1*2的骨牌堆积成4*N的矩形。一共同拥有多少种方法,N不超过10^9。

            这题和以前在庞果网上做过的一道木块砌墙差点儿一样。

    由于骨牌我们能够横着放。竖着放。我们如果以4为列,N为行这样去看,而且在骨牌覆盖的位置上置1,所以一共最多有16种状态。我们在第M行放骨牌的时候,第M+1行的状态也是有可能被改变的,设S(i,j)表示某一行状态为i时,将其铺满后下一行状态为j的方案书。考虑下如果我们让矩阵S和S相乘会有什么意义。考虑一下会发现S*S的意义当某行状态为i。接着其后面第2行的状态为j的可行方案数,一般地,S^n则代表接下来第n行状态为j的方案数,这里N非常大,我们能够用高速幂对矩阵的幂进行加速。

    对于S矩阵的最初状态我们能够穷尽搜索来求。

    #include <stdlib.h>
    #include <stdio.h>
    #include <vector>
    #include <math.h>
    #include <string.h>
    #include <string>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <algorithm>
    #include <stack>
    #include <map>
    
    #include<iostream>  
    #include<cstdio>  
    using namespace std;
    int State[16][16];
    int Start[16][16];
    int IMod;
    
    void InitState(int ori, int s, int p)
    {
    	bool isfull = true;
    	for (int i = 0; i < 4; i++)
    	{
    		if (((s >> i) & 1) == 0)
    		{
    			//竖着放
    			InitState(ori, s | (1 << i), p | (1 << i));
    			//横着放
    			if (i < 3 && ((s >> (i + 1)) & 1) == 0)
    			{
    				int tp = s | (1 << i);
    				tp |= (1 << (i + 1));
    				InitState(ori ,tp, p);
    			}
    			isfull = false;
    			break;
    		}
    	}
    	if (isfull)
    	{
    		State[ori][p] += 1;
    	}
    }
    
    void Product(int a[][16], int b[][16], int res[][16])
    {
    	for (int i = 0; i < 16;i++)
    	{
    		for (int j = 0; j < 16; j++)
    		{
    			res[i][j] = 0;
    			for (int k = 0; k < 16; k++)
    			{
    				res[i][j] += (a[i][k] * b[k][j] % IMod);
    				res[i][j] %= IMod;
    			}
    		}
    	}
    }
    
    void QProduct(int p[][16], int res[16][16], int n)
    {
    	memset(res, 0, sizeof(int) * 16 * 16);
    	int tmp[2][16][16];
    	int tmpres[16][16];
    	memcpy(tmp[0], p, sizeof(int) * 16 * 16);
    	int i = 0;
    	for (int k = 0; k < 16; k++)
    	{
    		res[k][k] = 1;
    	}
    	while (n)
    	{
    		
    		if (n & 1)
    		{
    			memcpy(tmpres, res, sizeof(int) * 16 * 16);
    			Product(tmpres, tmp[i & 1], res);
    		}
    		Product(tmp[i & 1], tmp[i & 1], tmp[(i + 1) & 1]);
    		i++;
    		n = n >> 1;
    	}
    }
    
    
    int main()
    {
    #ifdef _DEBUG
    	freopen("d:\in.txt", "r", stdin);
    #endif
    	int n, m;
    	memset(State, 0, sizeof(State));
    	for (int i = 0; i < 16; i++)
    	{
    		InitState(i, i, 0);
    	}
    	
    	int finstates[16][16];
    	int res[16][16];
    	memset(Start, 0, sizeof(Start));
    	Start[0][0] = 1;
    	while (scanf("%d %d", &n, &m) != EOF)
    	{
    		if (n == 0 || m == 0)
    		{
    			break;
    		}
    		IMod = m;
    		QProduct(State, finstates, n);
    		Product(Start, finstates, res);
    		int ans = 0;
    		for (int i = 0; i < 16; i++)
    		{
    			ans += res[i][0];
    			ans %= IMod;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }


  • 相关阅读:
    C#控件刷新
    [转载] 尺度不变特征变换匹配算法
    C++ windows 多线程 互斥锁
    堆栈内存申请,以及32位程序内存上限
    dumpbin检查Dll
    CV_Assert
    Linux复习
    操作系统复习
    P/NP问题
    程序
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6881387.html
Copyright © 2020-2023  润新知