算法习题-经典环形涂色问题
在对某个圆上色,具体步骤为:
首先在纸上画下一个圆,然后在圆
内画一个圆
,圆
内不上色。
现在将圆内除圆
的区域等分为
个部分,如图所示。对此
个部分使用
种颜色上色,使得相邻两个区域的颜色不同,问共有多少种不同方案,由于结果可能很大,对
取模后输出。 (对于两种不同的方案,只要有一个区域上色的颜色不同,我们即认为是不同的)
解题思路:
设 表示当有
个部分,
种颜色时的所有方案数。考虑当
时,
因为当只有一个部分时,没有相邻的部分,不满足条件,因此种类有 0 个。考虑当
时,
。当有
个部分时,可以分为两种情况:
1、 第 1 个和第 n-1 个相同时:第 n 个有 m-1 种选法,前 n-1 个的选法总数等于,因为第 1 个和第 n-1 个相同,因此相当于第 n-2 个直接连接在了第 1 个上,因此种数就相当于
因此,该种情况的总数为:
2、 第 1 个和第 n-1 个不同时:第 n 个有 m-2 种选法,而第 1 个到第 n-1 个就相当于一个完整的环,因此,种数为: 因此,该种情况的总数为:
由以上两种情况即可推导出递推式为:
进一步化简,利用特征方程,进行尝试求解
变换形式:原式 =
由于是二阶线性方程,
设 ,那末
,
故:
解得:,
,
带入:,
可得:
代码实现:
import java.util.*;
public class Main{static int p = (int)1e9 + 7;public static void main(String[] args) {Scanner sc = new Scanner(System.in);long n = sc.nextLong();long m = sc.nextLong();if(n == 2) System.out.println(m * (m-1) % p);else {long t1 = qmi(m-1,n);long t2 = (qmi(-1,n) * (m-1) + p) % p;System.out.println((t1 + t2) % p);}}static long qmi(long a,long k) {long res = 1;while(k != 0) {if((k & 1) == 1) res = res * a % p;a = a * a % p;k >>= 1;}return res;}
}