問題描述
如果一個自然數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-1的K好數的數目再此基礎上往末尾再添一位符合題目條件的數即可。
例如4進制的3位K好數,末尾位是2的可能性m[3][2]=m[2][0]+m[2][2]。m[2][2]=m[1][0]+m[1][2],由此可以總結出遞推方程如下:
設表示K進制i位K好數其末尾位是j的所有可能性是m[i][j]
則:
代碼
#include <iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<math.h>
//動態規劃
//用m[i][j]來表示長度爲i的末尾爲j的所有可能性數
//長度爲0的末尾爲j的m[0][j]=0;
//長度爲0的末尾爲j的m[1][j]=1(m[1][0]=0除外);
//體現不斷往末尾加一位的思想,加的這一位不能是其前一位的相鄰的數
//從m[i-1][j]到m[i][j]:m[i][j]=m[i-1][k](其中|k-j|!=1);
//最後結果sum=所有m[L][0...K-1]之和
long long m[101][101];
int main()
{
memset(m,0,sizeof(m));
int K,L;//K表示K進制,L表示L位數
cin>>K>>L;
//長度爲0的末尾爲j的m[0][j]=0;
for(int j=0;j<=K-1;j++)
m[0][j]=0;
//長度爲0的末尾爲j的m[1][j]=1(m[1][0]=0除外);
m[1][0]=0;
for(int j=1;j<=K-1;j++)
m[1][j]=1;
//開始規劃
for(int i=1;i<=L;i++)//最後要求的長度爲L
for(int j=0;j<=K-1;j++){//每一位的取值可以是0-(K-1)
for(int t=0;t<=K-1;t++)//往末尾加一位的可能取值也是0-(K-1)
if(t-j!=-1&&t-j!=1){
m[i][j]=m[i][j]+m[i-1][t];
m[i][j]=m[i][j]%1000000007;//以防整數過大取餘
}
}
long long sum;//定義結果
sum=0;
//sum的值爲數組m的第L行的從0-(K-1)所有元素之和
for(int i=0;i<=K-1;i++){
sum=sum+m[L][i];
sum=sum%1000000007;//以防整數過大取餘
}
cout<<sum;
return 0;
}