问题 C: 鲁的石板
题目描述
宇宙大帝 Luke 拥有一颗璀璨的星球,名为 Lu3KO5(鲁星),这颗星球上存在着一块古老的圆形祭坛。祭坛由 n 个扇形石板组成,每一块石板都有细微的不同。为了能够让祭坛展现出其神秘的力量,Luke 需要用 m 种不同颜色的神秘能量将这些石板染色(每一块石板都必须染色)。
然而,为了保持祭坛的神圣与美观,Luke 要求相邻的两块扇形石板不能染成同一种颜色的能量。现在,Luke 想知道共有多少种不同的染色方案能够满足这个要求(只要有一个位置的石板颜色不同就算不同的染法)。
作为宇宙大帝,Luke 一眼就能看出答案,但他认为这对他来说太过简单,于是将问题交给了聪明的你。你能帮助他计算出所有可能的染色方案吗?
输入
输入第一行为一个正整数 T,表示 T 组数据。
接下来 T 行每行两个正整数 n 和 m。
输出
对于每一组数据输出一个整数,表示染色方案数量模 1000000007 后的结果。
样例输入
7
1 1
3 5
5 5
4 4
1 2
100000 20
1000000000 50
样例输出
1
60
1020
84
29048415
90672511614
提示
对于 20% 的数据,\(1 ≤ T ≤ 5,1 ≤ n ≤ m ≤ 5\)
对于 50% 的数据,\(1 ≤ T ≤ 5,1 ≤ n ≤ 10^6\)。
对于 100% 的数据 \(1 ≤ T ≤ 10^5,1 ≤ n ≤ 10^9,1 ≤ m ≤ 50\)。
分析
这是一个环形染色问题,推导它的公式再用快速幂就是即可,
对于一个有\(n\)个区域环,有\(m\)个颜色可以选择,相邻的石块不能涂一样的颜色,将环从某两个区域分开,展开为一个线性排列,那么相邻元素不同的排列有\(m(m-1)^{n-1}\)种,设\(n\)个区域的环的涂色方案有\(a_n\)种,那么线性排列首位颜色有两种情况,
- 首位颜色相同,那么把首位两个区域叠成一个区域,那么组成了一个\(n-1\)个区域的环,就等于\(a_{n-1}\)
- 首位颜色不同,那么直接拼接首位成为一个\(m\)个区域的环,就等于\(a_n\)
综合两种情况,得到方程\(a_n + a_{n-1} = m(m-1)^{n-1}\),所以\(a_n = (m-1)^n + (-1)^n(m-1)\)
代码
#include<bits/stdc++.h>
#define de(x) cout << #x << "=" << (x) << '\n'
#define de2(x,y) cout << #x << "=" << (x) << #y << "=" << y << '\n';
using namespace std;#define int long long
const int N = 1e9+7;inline int fast_fact(int n, int m){int base = m-1, nub = n,ans = 1;while(nub){if(nub&1) ans = ans%N*base%N;nub /= 2;base = base%N*base%N;}return ans + (n&1 ? -(m-1):(m-1));
}
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;cin >> t;while(t--){int n, m;cin >> n >> m;if(n == 1) cout << m%N << '\n';else if(n == 2) cout << m%N*(m-1)%N << '\n';else if(n == 3) cout << m%N*(m-1)%N*(m-2) << '\n';else {cout << fast_fact(n,m) %N<< '\n';}}
}