1217. 垒骰子 dp 矩阵乘法 快速幂

赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。

经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!

我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。

假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。

atm想计算一下有多少种不同的可能的垒骰子方式。

两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。

由于方案数可能过多,请输出模 109+7 的结果。

输入格式
第一行包含两个整数 n,m,分别表示骰子的数目和排斥的组数。

接下来 m 行,每行两个整数 a,b,表示 a 和 b 数字不能紧贴在一起。

输出格式
共一个数,表示答案模 109+7 的结果。

数据范围
1≤n≤109,
1≤m≤36,
1≤a,b≤6
输入样例:
2 1
1 2
输出样例:
544

import java.util.*;

public class Main
{
	static int n,m,N=6,mod=1000000007;
	static int a[][]=new int [N][N],f[][]=new int[N][N];
	static int map(int x){
		return (x+3)%6;
	}
	static void mul(int c[][],int a[][],int b[][]){
		int t[][]=new int [N][N];
		for(int i=0;i<N;++i){
			for(int j=0;j<N;++j){
				for(int k=0;k<N;++k){
					t[i][j]=(int)((t[i][j]+(long)a[i][k]*b[k][j])%mod);
				}
			}
		}
		for(int i=0;i<N;++i){
			for(int j=0;j<N;++j){
				c[i][j]=t[i][j];
			}
		}
	}
	
	public static void main(String args[])
	{
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		m=sc.nextInt();
		for(int i=0;i<N;++i)Arrays.fill(a[i], 4);
		for(int i=0;i<N;++i)f[0][i]=4;
		while((m--)>0){
			int x,y;
			x=sc.nextInt();
			y=sc.nextInt();
			x--;y--;
			a[map(y)][x]=0;
			a[map(x)][y]=0;
		}
		
		n--;
		while(n>0){
			if(n%2==1)mul(f,f,a);
			mul(a,a,a);
			n>>=1;
		}
		int ans=0;
		for(int i=0;i<N;++i){
			ans=(ans+f[0][i])%mod;
		}
		System.out.println(ans);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wow_awsl_qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值