# 垒骰子 赌圣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$ 的结果。 **样例输入** ``` 2 1 1 2 ``` **样例输出 ** ``` 544 ``` **数据范围** ``` 对于 30% 的数据:n <= 5 对于 60% 的数据:n <= 100 对于 100% 的数据:0 < n <= 10^9, m <= 36 ``` **资源约定:** 峰值内存消耗 < 256M CPU消耗 < 2000ms 以下选项错误的是? ## aop ### before ```cpp #include using namespace std; ``` ### after ```cpp ``` ## 答案 ```cpp #define MOD 1000000007 using namespace std; int points[7] = {0, 4, 5, 6, 1, 2, 3}; int n, m; int ban[36][2]; long long result; bool judge(int point1, int point2) { bool flag = true; for (int i = 0; i < m; i++) { int point3 = points[point2]; if (point1 == ban[i][0] && point3 == ban[i][1]) { flag = false; break; } if (point1 == ban[i][1] && point3 == ban[i][0]) { flag = false; break; } } return flag; } void dfs(int cnt, int point) { if (cnt == n) { result++; return; } for (int i = 1; i <= 6; i++) { if (judge(point, i)) { cnt++; dfs(cnt, i); cnt--; } } } long long quickpow(int x, int N) { int reg = x; int sum = 1; while (N) { if (N & 1) { sum = sum * reg; } reg *= reg; N = N >> 1; } return sum; } int main() { cin >> n >> m; for (int i = 0; i < m; i++) { cin >> ban[i][0] >> ban[i][1]; } dfs(0, 0); long long temp = quickpow(4, n); cout << result * temp % MOD; return 0; } ``` ## 选项 ### A ```cpp #define MOD 1000000007 typedef long long LL; LL dp[2][7]; int n, m; bool conflict[7][7]; map op; 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) { 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] = (ans.a[i][j] + m1.a[i][k] * m2.a[k][j]) % MOD; } } } return ans; } M mPow(M m, int 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) { if (k & 1) { ans = mMultiply(ans, m); } m = mMultiply(m, m); k >>= 1; } return ans; } int main() { init(); scanf("%d%d", &n, &m); M cMatrix; for (int i = 0; i < m; ++i) { int a, b; scanf("%d%d", &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); LL 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; } } LL t = 1; LL tmp = 4; LL p = n; while (p) { if (p & 1) { t = t * tmp % MOD; } tmp = tmp * tmp % MOD; p >>= 1; } printf("%lld", ans * t % MOD); return 0; } ``` ### B ```cpp #define MOD 1000000007 typedef long long LL; LL dp[2][7]; int n, m; bool conflict[7][7]; map op; void init() { op[1] = 4; op[4] = 1; op[2] = 5; op[5] = 2; op[3] = 6; op[6] = 3; } int main() { init(); scanf("%d%d", &n, &m); for (int i = 0; i < m; ++i) { int a, b; scanf("%d%d", &a, &b); conflict[a][b] = true; conflict[b][a] = true; } for (int j = 1; j <= 6; ++j) { dp[0][j] = 1; } int cur = 0; for (int level = 2; level <= n; ++level) { cur = 1 - cur; for (int j = 1; j <= 6; ++j) { dp[cur][j] = 0; for (int i = 1; i <= 6; ++i) { if (conflict[op[j]][i]) continue; dp[cur][j] = (dp[cur][j] + dp[1 - cur][i]) % MOD; } } } LL sum = 0; for (int k = 1; k <= 6; ++k) { sum = (sum + dp[cur][k]) % MOD; } LL ans = 1; LL tmp = 4; LL p = n; while (p) { if (p & 1) ans = (ans * tmp) % MOD; tmp = (tmp * tmp) % MOD; p >>= 1; } printf("%lld\n", (sum * ans) % MOD); return 0; } ``` ### C ```cpp #define MOD 1000000007 int op[7]; bool confilct[7][7]; void init() { op[1] = 4; op[4] = 1; op[2] = 5; op[5] = 2; op[3] = 6; op[6] = 3; } int n, m; long long int f(int up, int count) { if (count == 0) return 4; long long ans = 0; for (int upp = 1; upp <= 6; ++upp) { if (confilct[op[up]][upp]) continue; ans = (ans + f(upp, count - 1)) % MOD; } return ans; } int main() { init(); scanf("%d%d", &n, &m); for (int i = 0; i < m; ++i) { int x, y; scanf("%d%d", &x, &y); confilct[y][x] = true; confilct[x][y] = true; } long long ans = 0; for (int up = 1; up <= 6; ++up) { ans = (ans + 4 * f(up, n - 1)) % MOD; } printf("%lli\n", ans); return 0; } ```