'lintcode 染色问题'

lintcode 染色问题

描述

有一个圆形,分成n个扇形,用m种颜色给每个扇形染色,相邻扇形颜色不能相同。求方案总数。

不考虑对称性。
由于这个数可能很大,因此只需返回方案数模1e9 + 7。
1≤n≤1051  1≤n≤10​^5​​
1≤m≤1051 1≤m≤10​5​^5

样例

给定n = 2,m = 3,返回6。

解释:
一个圆划分为 2 个扇形,用 3 种颜色上色方案有“黑红,黑白,白红,白黑,红白,红黑”6 种。

给定 n = 3,m = 2,返回 0。

解释:
一个圆划分为 3 个扇形,用 2 种颜色上色,无论怎么上色,都没法保证相邻的颜色不同。

思路

使用动态规划,考虑每多1块扇形可能的情况:

  1. 多的这一块扇形两边的颜色不一样
    如此,多的这一块有m-2种填法,剩下的n-1块的填法是f(n-1)。一共是f(n-1) * (m-2)
  2. 多的这一块两边的扇形颜色一样
    多的这一块有m-1种,剩下的图形是f(n-2)

两者相加就可以得到递推式:
f(n) = (m-1)f(n-2) + (m-2)f(n-1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
/**
* @param n: the number of sectors
* @param m: the number of colors
* @return: The total number of plans.
*/
int getCount(int n, int m) {
// Write your code here
vector dp(n+2, 0);
unsigned long long mod = 1e9+7;
dp[0] = 0;
dp[1] = m;
dp[2] = (unsigned long long)m*(m-1) % mod;
dp[3] = (unsigned long long)m*(m-1)*(m-2) % mod;
for (int i = 4; i < n+1; i++)
dp[i] = ((m-2)*dp[i-1] + (m-1)*dp[i-2]) % mod;
return dp[n];
}
};

这里要注意的是,dp[2] = (unsigned long long)m(m-1) % mod;
dp[3] = (unsigned long long)m
(m-1)(m-2) % mod;这两行,一开始的时候我没有加上强制类型转换 (unsigned long long)得出的结果一直是错的,加上之后就正确了。我猜想是因为m的类型是int,运算完m\(m-1)*(m-2)之后很有可能溢出了。所以我对这个操作进行了测试。

1
2
3
4
5
6
7
8
9
10
int int_m = 1999;

unsigned long long ull_m = 1999;

cout << "int: " << int_m * int_m * int_m << endl;

cout << "int(unsigned long long): " <<
(unsigned long long)int_m * int_m * int_m << endl;

cout << "unsigned long long: "<< ull_m * ull_m * ull_m << endl;

第一行输出为 -601928593
第二行输出为 7988005999
第三行输出为 7988005999
结果显而易见了。在运算的时候,遇到大数,一定要注意精度的问题。

-------------end of file thanks for reading-------------

你可能感兴趣的:('lintcode 染色问题')