算法訓練 K好數
時間限制:1.0s 內存限制:256.0MB
錦囊1
錦囊2
錦囊3
問題描述
如果一個自然數N的K進製表示中任意的相鄰的兩位都不是相鄰的數字,那麼我們就說這個數是K好數。求L位K進制數中K好數的數目。例如K = 4,L = 2的時候,所有K好數爲11、13、20、22、30、31、33 共7個。由於這個數目很大,請你輸出它對1000000007取模後的值。
輸入格式
輸入包含兩個正整數,K和L。
輸出格式
輸出一個整數,表示答案對1000000007取模後的值。
樣例輸入
4 2
樣例輸出
7
數據規模與約定
對於30%的數據,KL <= 106;
對於50%的數據,K <= 16, L <= 10;
對於100%的數據,1 <= K,L <= 100。
問題分析
問題的大意是,L位數的K進製表示中相鄰的兩位都不是相鄰的數字。 比如:L=2,K=4, 4進製表示的數字只能是0--3,則2位數的二進制,共有下面幾種可能:
10 ,11 ,12,13,20,21,22,23,30,31,32,33(注最高位不能爲0)。 由於相鄰的兩位都不是相鄰的數字,所以K好數爲11,13,20,22,30,31,33共7個。
解決方法 : (動態規劃)
這裏首先對動態規化做簡單描述,具體可以自己查找視頻。
動態規劃(Dynamic Programming)就是將求解的子問題分解爲若干個子問題,按順序求解子問題,前一個子問題的解爲後一子問題的求解提供了有用的信息。狀態轉移 方程是動態規劃的關鍵。
本題的解題思想:因爲有L位數,從最低位開始依次作爲子問題。比如:L=2,K=4
代碼實現:
#include<iostream>
#include<cstring>
using namespace std;
const int MAX = 101;
const int M = 1000000007;
int f[MAX][MAX];
int main()
{
int l, k;
while(cin>>k>>l)
{
//特殊處理
if(l == 1)
{
cout<<k-1<<endl;
}
else
{
memset(dp, 0, sizeof(dp));
//初始化
for(int i=0; i<k; i++)
{
f[1][i] = 1;
}
for(int i=2; i<l; i++)//第2位到l-1位
{
for(int j=0; j<k; j++)//可能取值0-k-1
{
int cnt = 0;
for(int r=0; r<k; r++)
{
if(r == j-1 || r == j+1) //相鄰爲不能相同
{
continue;
}
cnt = (cnt + f[i-1][r])%M;
}
f[i][j] = cnt;
}
}
int sum = 0;
//對最高位進行處理
for(int j=1; j<k; j++)
{
int cnt=0;
for(int r=0; r<k; r++)
{
if(r == j-1 || r == j+1)
{
continue;
}
cnt = (cnt + f[l-1][r])%M;
}
sum = (sum+cnt)%M;
}
cout<<sum<<endl;
}
}
return 0;
}