• 【洛谷P5303】逼死强迫症


    前言

    这道题给我平测了\(3min+\)才出结果。。。可真是逼死我了。

    题目

    题目链接:https://www.luogu.com.cn/problem/P5303
    ITX351 要铺一条 \(2 \times N\) 的路,为此他购买了 \(N\)\(2 \times 1\) 的方砖。可是其中一块砖在运送的过程中从中间裂开了,变成了两块 \(1 \times 1\) 的砖块!
    ITX351 由此产生了一个邪恶的想法:他想要在这条路上故意把两块 \(1 \times 1\) 的砖块分开铺,不让两块砖有相邻的边,其他砖块可以随意铺,直到整条路铺满。这样一定可以逼死自身强迫症 sea5!
    也许下面的剧情你已经猜到了——他为此兴奋不已,以至于无法敲键盘。于是,他请你帮忙计算一下,有多少种方案可以让自己的阴谋得逞。

    思路

    数据范围明显提示这道题是矩阵乘法。
    有一个十分明显的结论,假设两个\(1\times 1\)的方砖分别位于第\(i,j\)列(\(i<j\)\(j-i\geq 2\)),那么第\(i\sim j\)列仅有\(2\)种放法,前\(i-1\)列有\(fib[i-1]\)种放法。

    证明:
    如果第\(i\sim j\)列中有一列是竖着摆放方砖的,那么显然会把第\(i\sim j\)列构成的矩形分为两个大小为奇数的部分,而每一个\(1\times 2\)方砖的大小为偶数,所以肯定铺不满。所以只能横着放。
    而横着放时不可以中间空一格否则就永远无法填满,所以必须一个接着一个放。画图后容易发现要满足这些要求只有\(2\)中情况。
    \(i-1\)列只能用\(1\times 2\)的方砖摆放,摆放的方案其实只有“在最后一列加上一个\(1\times 2\)的方砖”和“在最后一个\(2\times 2\)的正方形中横着放两块方砖”,设用\(2\times 1\)的方砖摆放\(2\times i\)的路面的方案数为\(g[i]\),那么就有\(g[i]=g[i-1]+g[i-2]\),边界为\(g[1]=1,g[2]=2\)。容易发现这是一个斐波那契数列,前\(i-1\)列有\(fib[i-1]\)种放法。
    证毕。

    先写出递推式。设\(f[i]\)表示\(n=i\)时的方案数。那么有三种情况。

    1. 在最后一列加上一个\(1\times 2\)的方砖,共\(f[i-1]\)种方案。
    2. 在最后一个\(2\times 2\)的正方形中横着放两块方砖(竖着放其实就是第一种情况),共\(f[i-2]\)种情况。
    3. 在最后一列放一个\(1\times 1\)的方砖。假设另一个\(1\times 1\)的方砖放在第\(j\)列,根据上文的结论,有方案数=\(2\sum^{i-3}_{j=0}fib[j]\)

    所以我们就得到了递推式

    \[f[i]=f[i-1]+f[i-2]+2\sum^{i-3}_{j=0}fib[j] \]

    其中\(fib[0]=fib[1]=1,fib[i]=fib[i-1]+fib[i-2](i>1)\)
    那么可以构建一个\(5\times 5\)的矩阵,分别表示\(f[i],f[i-1],s[i-3],fib[i-3],fib[i-4]\),其中\(s[x]\)表示前\(x\)个斐波那契数之和。
    那么转移矩阵如下

    \[\begin{bmatrix} 1& 1 & 0 & 0 & 0\\ 1& 0 & 0 & 0 & 0\\ 2& 0 & 1 & 0 & 0\\ 0& 0 & 1 & 1 & 1\\ 0& 0 & 1 & 1 & 0 \end{bmatrix}\]

    初始矩阵如下

    \[\begin{bmatrix} 6 & 2 &4 &2 &1 \end{bmatrix}\]

    时间复杂度\(O(Tm^3\log n)\),其中\(m=5\)

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MOD=1000000007,N=6;
    int n,T;
    
    struct matrix
    {
    	int a[N][N];
    	
    	friend matrix operator *(matrix a,matrix b)
    	{
    		matrix c;
    		memset(c.a,0,sizeof(c.a));
    		for (int i=1;i<N;i++)
    			for (int j=1;j<N;j++)
    				for (int k=1;k<N;k++)
    					c.a[i][j]=(c.a[i][j]+1LL*a.a[i][k]*b.a[k][j]%MOD)%MOD;
    		return c;
    	}
    }a,f,A,F;
    
    void power(int k)
    {
    	for (;k;k>>=1,a=a*a)
    		if (k&1) f=f*a;
    }
    
    int main()
    {
    	A.a[1][1]=A.a[1][2]=A.a[2][1]=A.a[3][3]=A.a[4][3]=A.a[4][4]=A.a[4][5]=A.a[5][3]=A.a[5][4]=1;
    	A.a[3][1]=2; 
    	F.a[1][1]=6; F.a[1][2]=2; F.a[1][3]=4; F.a[1][4]=2; F.a[1][5]=1;
    		
    	scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%d",&n);
    		if (n==1 || n==2) printf("0\n");
    		else if (n==3) printf("2\n");
    		else if (n==4) printf("6\n");
    		else
    		{
    			memcpy(a.a,A.a,sizeof(a.a));
    			memcpy(f.a,F.a,sizeof(f.a));
    			power(n-4);
    			printf("%d\n",f.a[1][1]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    hdu 1863 畅通工程
    poj 2524 Ubiquitous Religions
    04 Linux终端命令01
    05 linux中yum源报错
    Filterg过滤器和Listener监听器
    03 Centos的文件目录、远程连接工具及快照操作
    02 安装虚拟机以及设置虚拟机网卡信息
    01VM虚拟机介绍及配置虚拟机网卡信息
    Jstl表达式
    EL表达式
  • 原文地址:https://www.cnblogs.com/stoorz/p/12229993.html
Copyright © 2020-2023  润新知