P8624

[蓝桥杯 2015 省 AB] 垒骰子

题目描述

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

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

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

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

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

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

由于方案数可能过多,请输出模 \(10^9+7\) 的结果。

不要小看了 atm 的骰子数量哦~。

输入格式

第一行两个整数 \(n\)\(m\)

\(n\) 表示骰子数目。

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

输出格式

一行一个数,表示答案模 \(10^9+7\) 的结果。

样例 #1

样例输入 #1

2 1
1 2

样例输出 #1

544

提示

对于 \(30\%\) 的数据:\(n \le 5\)

对于 \(60\%\) 的数据:\(n \le 100\)

对于 \(100\%\) 的数据:\(0<n \le 10^9,m \le 36\)

时限 2 秒, 256M

这题很好地复习了滚动数组
这题有个坑点:最后还要×4^n
f[i][j]:第i个 j面朝上
f[i][j]+=f[i-1][k] if(j 与 k 不排斥)
由于只跟前一个阶段有关 故可以滚动数组

注意滚动数组每次滚动时要清零!!!

这样已经可以得84pts了 还有一个TLE是因为要用矩阵快速幂优化 以后再补
84pts DP
#include<bits/stdc++.h>
using namespace std;
#define int long long
int f[3][7];
const int mod=1e9+7;
int n,m;
int pd[7][7],ma[7];
signed main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	ma[1]=4,ma[4]=1,ma[2]=5,ma[5]=2,ma[3]=6,ma[6]=3;
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		pd[a][b]=pd[b][a]=1;
	}
	int now=1;
	for(int i=1;i<=6;i++)f[1][i]=1;
	for(int i=2;i<=n;i++)
	{
		now=3-now;
		for(int j=1;j<=6;j++)
		{
			f[now][j]=0;
			for(int k=1;k<=6;k++)
			{
				if(pd[k][ma[j]])continue;
				f[now][j]+=f[3-now][k];
				f[now][j]%=mod;
			}
		}
		
	}
	int tot=0;
	
	if(n&1)
	{
		for(int i=1;i<=6;i++)tot+=f[1][i];
	}
	else
	{
		for(int i=1;i<=6;i++)tot+=f[2][i];
	}
	for(int i=1;i<=n;i++)tot=tot*4%mod;
	cout<<tot<<"\n";
	return 0;
}
posted @ 2023-01-10 11:54  PKU_IMCOMING  阅读(6)  评论(0)    收藏  举报