算法习题-经典环形涂色问题

在对某个圆上色,具体步骤为:  
首先在纸上画下一个圆O_1,然后在圆O1内画一个圆O2,圆O2 内不上色。  
现在将圆O1内除圆O2的区域等分为n个部分,如图所示。对此n个部分使用m种颜色上色,使得相邻两个区域的颜色不同,问共有多少种不同方案,由于结果可能很大,对10^9+7取模后输出。 (对于两种不同的方案,只要有一个区域上色的颜色不同,我们即认为是不同的)

解题思路:

a_n 表示当有n个部分,m种颜色时的所有方案数。考虑当n=1时,a_1=0因为当只有一个部分时,没有相邻的部分,不满足条件,因此种类有 0 个。考虑当n=2时,a_2=m*(m-1)。当有n个部分时,可以分为两种情况:

       1、 第 1 个和第 n-1 个相同时:第 n 个有 m-1 种选法,前 n-1 个的选法总数等于a_{n-2},因为第 1 个和第 n-1 个相同,因此相当于第 n-2 个直接连接在了第  1 个上,因此种数就相当于a_{n-2}因此,该种情况的总数为:(m-1)*a_{n-2}
       2、 第 1 个和第 n-1 个不同时:第 n 个有 m-2 种选法,而第 1 个到第 n-1 个就相当于一个完整的环,因此,种数为: a_{n-1} 因此,该种情况的总数为:(m-2) * a_{n-1}

由以上两种情况即可推导出递推式为:a_{n}=(m-2)*a_{n-1}+(m-1)*a_{n-2}\left ( n \geqslant 3 \right )

进一步化简,利用特征方程,进行尝试求解

变换形式:原式 = a_n-(m-2)*a_{n-1}-(m-1)*a_{n-2}=0
由于是二阶线性方程,

设 a_n=r^n,那末 a_{n-1}=r^{n-1}a_{n-2}=r^{n-2}
故:r^n-(m-2)*r^{n-1}-(m-1)*r^{n-2}=0
解得:r_1=-1r_2=m-1a_n=A*r_1^n+B*r_2^n

带入:a_1=0a_2=m*((m-1)
可得:a_n=(m-1)^n+(-1)^n*(m-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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值