题目
n个人排成一个环形,每个人要从c种颜色中选择一个。牛牛希望相邻的人选择的颜色是不同的,问有多少种方案。输出方案数对10007取模的结果。
注:人是有顺序的,环旋转同构算不同的方案。
R
n
m
=
(
m
−
1
)
n
+
(
m
−
1
)
⋅
(
−
1
)
n
R_n^m=(m-1)^n+(m-1)\cdot(-1)^n
Rnm=(m−1)n+(m−1)⋅(−1)n这以前老师上课讲的,下面推一下
有递推公式
f
n
+
f
n
−
1
=
c
⋅
(
c
−
1
)
n
−
1
f_n+f_{n-1}=c\cdot(c-1)^{n-1}
fn+fn−1=c⋅(c−1)n−1
右侧很显然,就是第一个位置确定后,依次填后面
n
−
1
n-1
n−1个位置,且不管第一个位置与最后一个位置的颜色是否相同
最后一个与第一个颜色相同,那么与第二个颜色必不同,那就可以把第一个抠掉,即
f
n
−
1
f_{n-1}
fn−1
与第一个颜色不同,那符合
f
n
f_n
fn的条件,那么左侧显而易见
下面就简单了
f
n
−
1
+
f
n
−
2
=
c
⋅
(
c
−
1
)
n
−
2
f_{n-1}+f_{n-2}=c\cdot(c-1)^{n-2}
fn−1+fn−2=c⋅(c−1)n−2
两式相减,得
f
n
−
f
n
−
2
=
c
⋅
(
c
−
1
)
n
−
2
⋅
(
c
−
2
)
f_n-f_{n-2}=c\cdot(c-1)^{n-2}\cdot(c-2)
fn−fn−2=c⋅(c−1)n−2⋅(c−2)
再加下一式,减下下式……以此类推
正着做就这么做,倒着的话数规就行了,也方便
#include<bits/stdc++.h>
using namespace std;
const int M=10007;
int n,m;
int pw(int x,int y){
int z=1;
for (;y;y>>=1,x=x*x%M)
if (y&1) z=z*x%M;
return z;
}
int main(){
scanf("%d%d",&n,&m);
printf("%d",pw(m-1,n)+(n&1?-1:1)*(m-1));
}