lintcode 染色問題
阿新 • • 發佈:2018-11-22
lintcode 染色問題
描述
有一個圓形,分成n個扇形,用m種顏色給每個扇形染色,相鄰扇形顏色不能相同。求方案總數。
不考慮對稱性。
由於這個數可能很大,因此只需返回方案數模1e9 + 7。
1≤n≤1051 1≤n≤10^5
1≤m≤1051 1≤m≤105^5
樣例
給定n = 2,m = 3,返回6。
解釋:
一個圓劃分為 2 個扇形,用 3 種顏色上色方案有“黑紅,黑白,白紅,白黑,紅白,紅黑”6 種。
給定 n = 3,m = 2,返回 0。
解釋:
一個圓劃分為 3 個扇形,用 2 種顏色上色,無論怎麼上色,都沒法保證相鄰的顏色不同。
思路
使用動態規劃,考慮每多1塊扇形可能的情況:
- 多的這一塊扇形兩邊的顏色不一樣
如此,多的這一塊有m-2種填法,剩下的n-1塊的填法是f(n-1)。一共是f(n-1) * (m-2) - 多的這一塊兩邊的扇形顏色一樣
多的這一塊有m-1種,剩下的圖形是f(n-2)
兩者相加就可以得到遞推式:
f(n) = (m-1)f(n-2) + (m-2)f(n-1)
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<unsigned long long> 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)之後很有可能溢位了。所以我對這個操作進行了測試。
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
結果顯而易見了。在運算的時候,遇到大數,一定要注意精度的問題。