蓝桥:省-15-A-9垒骰子-矩阵

省-15-A-9垒骰子-矩阵

 //根据递推式dp[i][j]=dp[i-1][1]+dp[i-1][2]+dp[i-1][3]+dp[i-1][4]+dp[i-1][5]+dp[i-1][6](j=1~6且不能冲突)
 //第二层f2=T*(1,1,1,1,1,1)^(T),这个T为矩阵的转置 ,这个向量为列向量 
 //第n层为(1,1,1,1,1,1)^(T)不断左乘冲突矩阵T
 //fn=T^(n-1)*(1,1,1,1,1,1)^(T)
 //最终fn*4^(n)
#define MOD 1000000007
typedef long long LL;
#include<map>
#include<vector>
#include<iostream>
using namespace std;
map<int,int>op;
//int flag[7][7];
int n,m;
void init(){
	op[1]=4;
	op[4]=1;
	op[2]=5;
	op[5]=2;
	op[3]=6;
	op[6]=3;
} 
struct M{
	LL a[6][6];
	M(){
		for(int i=0;i<6;i++){
			for(int j=0;j<6;j++){
				a[i][j]=1;
			}
		}
	}
}; 
M mMultiply(M m1,M m2){ //矩阵M1*M2 
	M ans;
	for(int i=0;i<6;++i){
		for(int j=0;j<6;++j){
			ans.a[i][j]=0;
			for(int k=0;k<6;++k){
				//ans.a[i][j]+=m1.a[i][k]*m2.a[k][j];
				ans.a[i][j]=(ans.a[i][j]+m1.a[i][k]*m2.a[k][j])%MOD;
			}
		}
	}
	return ans;
}
M mPow(M m,int k){	//求M的k次方 
	M ans;//单位矩阵
	for(int i=0;i<6;++i){
		for(int j=0;j<6;++j){
			if(i==j)ans.a[i][j]=1;
			else ans.a[i][j]=0;
		}
	} 
	
	while(k!=0){	//快速幂
		if((k&1)==1){
			ans=mMultiply(ans,m);
		}
		m=mMultiply(m,m);
		k>>=1;//k的二进制数向右移动一位 
	}
	return ans; 
}
int main(){
	init();
	M cMatrix;//冲突矩阵 
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		cMatrix.a[op[a]-1][b-1]=0;
		cMatrix.a[op[b]-1][a-1]=0;
	}
	M cMatrix_n_1=mPow(cMatrix,n-1);//冲突矩阵的n-1次方
	long long ans=0;
	for(int j=0;j<6;j++){
		for(int i=0;i<6;i++){
			ans=(ans+cMatrix_n_1.a[i][j])%MOD;	//ans为冲突矩阵的所有元素和 
		}
	}
	
	long long t=1;		//t为结果							//快速幂,求4的n次方 
	long long tmp=4;	//tmp为当前位权重 
	long long p=n;		//p位幂的次数 
	while(p!=0){
		if(p&1==1) t=(t*tmp)%MOD;//p当前最低为若位1,则将结果t加上该位权重 
		tmp=(tmp*tmp)%MOD;//更新权重 
		p>>=1;			//p作为二进制数每次向右移动移位,即除以2 
	} 
	printf("%lli",ans*t%MOD); 
	return 0;
}
//99593115 3 4 4 3 3 3 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值