【矩阵乘法】CDOJ1610 黑红梅方

考虑用4^n-不存在连续4个相同的。

f(i,j,k,l)表示以i为结尾的序列,最后三位分别是j,k,l时的方案。

可以转移,写一个64*64的转移矩阵。

貌似可以优化?……未完待续。

#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
#define MOD 1000000009ll
typedef vector<ll> vec;
typedef vector<vec> mat;
mat I;
mat operator * (const mat &A,const mat &B){
	mat C(A.size(),vec(B[0].size()));
	for(int i=0;i<A.size();++i){
		for(int k=0;k<B.size();++k){
			for(int j=0;j<B[0].size();++j){
				C[i][j]=(C[i][j]+A[i][k]*B[k][j]%MOD)%MOD;
			}
		}
	}
	return C;
}
mat Quick_Pow(mat a,ll p)
{
    if(!p){
    	return I;
    }
    mat res=Quick_Pow(a,p>>1ll);
    res=res*res;
    if((p&1ll)==1ll){
    	res=res*a;
    }
    return res;
}
ll Quick_Pow(ll a,ll p)
{
    if(!p){
    	return 1;
    }
    ll res=Quick_Pow(a,p>>1ll);
    res=res*res%MOD;
    if((p&1ll)==1ll){
    	res=(a%MOD*res)%MOD;
    }
    return res;
}
ll n;
int main(){
	cin>>n;
	I.assign(64,vec(64));
	for(int i=0;i<64;++i){
		for(int j=0;j<64;++j){
			I[i][j]=0;
		}
	}
	for(int i=0;i<64;++i){
		I[i][i]=1;
	}
	mat A(64,vec(1));
	for(int i=0;i<64;++i){
		A[i][0]=1;
	}
	mat b(64,vec(64));
	for(int i=0;i<64;++i){
		for(int j=0;j<64;++j){
			b[i][j]=0;
		}
	}
	for(int i=0;i<4;++i){
		for(int j=0;j<4;++j){
			for(int k=0;k<4;++k){
				int hang=i*16+j*4+k;
				if(i==j || j==k || i==k){
					for(int l=0;l<4;++l){
						int lie=l*16+i*4+j;
						b[hang][lie]=1;
					}
				}
				else{
					for(int l=0;l<4;++l){
						if(l==i || l==j || l==k){
							int lie=l*16+i*4+j;
							b[hang][lie]=1;
						}
					}
				}
			}
		}
	}
//	for(int i=0;i<64;++i){
//		for(int j=0;j<64;++j){
//			printf("%I64d ",b[i][j]);
//		}
//		puts("");
//	}
	mat c=Quick_Pow(b,n-3ll)*A;
	ll n4=Quick_Pow(4ll,n);
	ll tmp=0;
	for(int i=0;i<64;++i){
		tmp=(tmp+c[i][0])%MOD;
	}
	cout<<(n4-tmp+MOD)%MOD<<endl;
	return 0;
}
时间: 2024-08-05 16:00:30

【矩阵乘法】CDOJ1610 黑红梅方的相关文章

UESTC1610 黑红梅方

题意:一行有n个扑克牌,每一个扑克牌有四种颜色,问有几种扑克牌,满足连续四个不相等 题解:状态压缩+递推+矩阵快速幂,不过状态很多,不能直接写,这里分为5种状态 #include <bits/stdc++.h> #define maxn 5 const long long mod = (1e9+9); using namespace std; struct mat{ long long m[maxn][maxn], len; mat(){memset(m, 0, sizeof(m));len=

我们可以推测矩阵乘法最优解的时间复杂度么?

矩阵乘法的定义为: 按照定义,一个简单的方阵乘法伪代码如下: int A[48,48],B[48,48],C[48,48] for i in 1 to 48 for j in 1 to 48 for k in 1 to 48 C[i,j]+=B[i,k]*A[k,j] 三层嵌套,时间复杂度为O(n3),n为方阵的边长. 由于矩阵乘法的广泛运用,如何优化矩阵乘法运算,有重要的意义.在不考虑矩阵的疏密程度下,如何有效减少矩阵乘法中算术乘法的使用次数是一个主要的优化方向. 最早的矩阵乘法优化算法,是由

【BZOJ2510】弱题 期望DP+循环矩阵乘法

[BZOJ2510]弱题 Description 有M个球,一开始每个球均有一个初始标号,标号范围为1-N且为整数,标号为i的球有ai个,并保证Σai = M. 每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个球标号为k(k < N),则将它重新标号为k + 1:若这个球标号为N,则将其重标号为1.(取出球后并不将其丢弃) 现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数. Input 第1行包含三个正整数N,M,K,表示了标号与球的个数以及操作次数. 第2行包含N个

学习心得:《十个利用矩阵乘法解决的经典题目》from Matrix67

本文来自:http://www.matrix67.com/blog/archives/tag/poj大牛的博文学习学习 节选如下部分:矩阵乘法的两个重要性质:一,矩阵乘法不满足交换律:二,矩阵乘法满足结合律经典题目1 给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置.操作有平移.缩放.翻转和旋转    这 里的操作是对所有点同时进行的.其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心.如果对每个点分别进行模拟,那么m个操作总共耗时 O(mn).利用矩阵乘法可

[矩阵乘法][DP]Vijos1067 Warcraft III 守望者的烦恼

题目梗概 n个单位的路程,主角每次最多可以走k个单位(也就是每次可以走1-k个单位),问最后到第n个监狱的方法数. 思考 DP转移方程并不难推导: dp[i]表示第i个监狱的方法数 $dp\left [ i \right ] = dp\left [ i-1 \right ] + dp\left [ i-2 \right ]\cdots \cdots + dp\left [ i-k-1 \right ]$ 但是这个n有点太大了,所以我们需要对DP方程进行优化. 仔细观察转移方程会发现,每次都是加上

【bzoj5082】弗拉格 矩阵乘法

题目描述 给你n个flag,你要把每个染色成红黑白黄四色之一,满足: 1.相邻旗不能同色 2.白不能和黄相邻,红不能和黑相邻 3.不能存在连续三个球依次是“黑白红”或“红白黑” 4.翻转后相等视为等价 设不等价方案数为f(n),给定l,r,求 Sigma f(i),其中L<=i<=R模1000000007 输入 输入两个数l,r l, r ≤ 10^9 输出 输出答案 样例输入 3 4 样例输出 23 题解 矩阵乘法 容易设出dp状态 $f[i][j][k]$ 表示前 $i$ 个flag,最后

矩阵乘法&amp;&amp;矩阵快速幂&amp;&amp;最基本的矩阵模型——斐波那契数列

矩阵,一个神奇又令人崩溃的东西,常常用来优化序列递推 在百度百科中,矩阵的定义: 在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合 ,最早来自于方程组的系数及常数所构成的方阵.这一概念由19世纪英国数学家凯利首先提出. 好,很高深对吧.那我们就更加直接地理解一下矩阵的实质:二维数组 好了这个SB都会,就不解释了 同二维数组一样,矩阵是一个'纵横排列的二维数据表格',它一般是一个n*m的二维数组,其中n*m表示它有n行m列 每一位上的数可以用下标i,j来表示,形如这样一个矩阵:

1571:基础练习 矩阵乘法

题目:https://acmore.cc/problem/LOCAL/1571#desc 解法一:二维数组(因为二维数组不能作为函数的返回值,所以处理起来比较麻烦,此时推荐使用vector表示二维数组,请看解法二) 1 #include <iostream> 2 3 using namespace std; 4 5 int a[30][30] = { 0 }; //初始矩阵 6 int b[30][30] = { 0 }; //结果矩阵 7 8 int getMultiSum(int a1[]

深入浅出计算机组成原理:SIMD:如何加速矩阵乘法?(第27讲)

一.引子 上一讲里呢,我进一步为你讲解了CPU里的“黑科技”,分别是超标量(Superscalar)技术和超长指令字(VLIW)技术. 超标量(Superscalar)技术能够让取指令以及指令译码也并行进行:在编译的过程,超长指令字(VLIW)技术可以搞定指令先后的依赖关系,使得一次可以取一个指令包. 不过,CPU里的各种神奇的优化我们还远远没有说完.这一讲里,我就带你一起来看看,专栏里最后两个提升CPU性能的架构设计.它们分别是,你应该常常听说过的 超线程(Hyper-Threading)技术