Description
WYF画了一个极为不规则的n边形,画面太美简直不看,没有任意两条边长度是相等的。因为形状太难看了,做他同桌的CWQ看不下去了,趁着WYF上厕所的时间准备用他书包里的m种颜色的彩笔给n边形的边上色。但由于WYF画的实在太大,CWQ不知如何下手,他想知道他有多少种染色方法,能够使得每两条相邻 边不同色。你只需输出答案模10^9+7的结果。
Input
一行,仅包含两个正整数n和m。
Output
一个正整数,表示答案模10^9+7的结果
Sample Input
3 3
Sample Output
6
Data Constraint
对于50%的数据,3≤n≤100000,3≤m≤10;
对于100%的数据,3≤n≤10^18,3≤m≤50。
对于100%的数据,3≤n≤10^18,3≤m≤50。
题解
- 假设我们有n个点,方案数为A[n]
- 现在考虑加入第n个点,加入点后左右不同颜色,插入之前的方案数为A[n-1],该点的颜色有m-2中选取的方案
- 若加入点后左右同色,则删掉一个点后就符合条件了,方案数就为A[n-2],该点的颜色就有m-1种选取的方案
- 递推公式就是为A[n]=A[n-1]*(m-2)+A[n-2]*(m-1),通项公式为A[n]=(m-1)^n+(m-1)*(-1)^n
- 递推公式要矩阵乘法加速,通项公式直接快速幂就好了
代码
#include<cstdio> #define ll long long #define mo 1000000007 using namespace std; ll n,m,r; ll ksm(ll a,ll b) { for (r=1;b;b>>=1,a=a*a%mo) if (b&1) r=r*a%mo; return r; } int main() { freopen("color.in","r",stdin),freopen("color.out","w",stdout),scanf("%lld%lld",&n,&m); printf("%lld\n",(ksm(m-1,n)+(m-1)*ksm(-1,n))%mo); return 0; }