垒骰子
垒骰子
赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。
经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!
我们先来规范一下骰子: 的对面是 , 的对面是 , 的对面是 。
假设有 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。
atm想计算一下有多少种不同的可能的垒骰子方式。
两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。
由于方案数可能过多,请输出模 的结果。
输入格式
第一行包含两个整数 ,分别表示骰子的数目和排斥的组数。
接下来 行,每行两个整数 ,表示 和 数字不能紧贴在一起。
输出格式
共一个数,表示答案模 的结果。
数据范围
,
,
输入样例:
2 1 1 2
输出样例:
544
解题思路
如果的数据范围很小的话,可以用动态规划来做。
当然,因为会有一些限制,比如有和不可以贴在一起,那么有些集合就会变成空集。例如有,那么对应的就是空集;有,那么对应的就是空集(和的对立面分别是和)。
因此我们可以简化成,其中等于或,如果有限制条件约数那么就等于,否则等于。
这种做法的时间复杂度是,由于取到,因此会超时。
我们可以发现对于,有,其中每一个系数即都与的相同,因为对于同一个,他们的在每一层的限制都是一样的。因此可以抽象成矩阵相乘的形式。
设有向量
设有矩阵
其中根据是否有限制取或。
可以发现有。递推,有。矩阵相乘有结合律,因此可以用快速幂来求。
如何确定矩阵的值?假设有限制和不可以贴在一起,那么如果第个骰子最上面的数字是,那么在它上面的第个骰子的最上面的数字不可以是(和不可以贴一起,而的对立面是),而是通过向量与矩阵的第列相乘得到的,因此矩阵中的就为。同理可得。更一般的形式,如果有限制和,那么就有,其中表示的对立面。
因为我们实现的函数是矩阵乘矩阵,因此为了统一方便,我们把向量也扩充乘一个矩阵,除了第一行外,其余都为。
AC代码如下,时间复杂度为:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 typedef long long LL; 7 8 const int N = 6, mod = 1e9 + 7; 9 10 int mp[N] = {3, 4, 5, 0, 1, 2}; // 各个面的对立面映射 11 12 void mult(int c[][N], int a[][N], int b[][N]) { // C = A * B 13 int tmp[N][N] = {0}; 14 for (int i = 0; i < N; i++) { 15 for (int j = 0; j < N; j++) { 16 for (int k = 0; k < N; k++) { 17 tmp[i][j] = (tmp[i][j] + (LL)a[i][k] * b[k][j]) % mod; 18 } 19 } 20 } 21 22 memcpy(c, tmp, sizeof(tmp)); 23 } 24 25 int main() { 26 int n, m; 27 scanf("%d %d", &n, &m); 28 29 int a[N][N]; 30 for (int i = 0; i < N; i++) { 31 for (int j = 0; j < N; j++) { 32 a[i][j] = 4; // 一开始先把矩阵的值都初始化为4 33 } 34 } 35 36 while (m--) { 37 int x, y; 38 scanf("%d %d", &x, &y); 39 x--, y--; // 为了方便,把1~6映射到0~5 40 a[x][mp[y]] = a[y][mp[x]] = 0; // 有限制的数字取0 41 } 42 43 // F(1)一开始为一个全4的行向量(只有一个骰子,没有限制,每个数字都有4个方向),同时把向量扩展为矩阵 44 int f[N][N] = {4, 4, 4, 4, 4, 4}; 45 for (int i = n - 1; i; i >>= 1) { // 快速幂 46 if (i & 1) mult(f, f, a); // F = F * A 47 mult(a, a, a); // A = A * A 48 } 49 50 int ret = 0; 51 for (int i = 0; i < N; i++) { 52 ret = (ret + f[0][i]) % mod; 53 } 54 printf("%d", ret); 55 56 return 0; 57 }
参考资料
AcWing 1217. 垒骰子(蓝桥杯C++ AB组辅导课):https://www.acwing.com/video/793/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16000862.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-03-14 一元多项式的乘法与加法运算