1. 程式人生 > >藍橋杯 k好數 動態規劃

藍橋杯 k好數 動態規劃

對於30%的資料,KL <= 106

對於50%的資料,K <= 16, L <= 10;

對於100%的資料,1 <= K,L <= 100。

k好數思路:要得到所有的L位K進位制數的k好數,我們需要先得到L-1位K進位制數的k好數,再將其中第L位與第L-1位相鄰的數去掉即可。(子問題

如果理解了上面那句話,那麼我們只需要從1位開始遞推到L位的K進位制數即可。

定義一個二維陣列dp[i][j],其中 i表示位數 j表示第一位數

即求出1位K進位制數的k好數個數,dp[1][j],求出2位K進位制數的k好數個數 dp[2][j],如此遞推下去直到L位,

再將儲存L位開頭從1到K-1的K進位制的k好數相加

AC程式碼片段如下:

結合程式碼更好理解一點

 #include<iostream>
#include<algorithm>
#include<memory.h>
using namespace std;
#define mod 1000000007  
typedef long long ll;
ll dp[110][110];   //dp[i][j] 表示 i 位數 且 j為第一位的k好數個數
int k;				//k進位制 
int l;  			//l位數 
int main()
{
	ll sum=0;				//總計 
	cin>>k>>l;
	memset(dp,0,sizeof(dp));
	for(int j=0;j<k;j++){	
		dp[1][j] =1;		//1位數的K好數    
	}
	for(int i=2;i<=l;i++){  		//從2位數到l位數,動態規劃 
		for(int j=0;j<k;j++){		//第一位數為j 
			for(int f=0;f<k;f++){	//第二位數為f 
				if(f+1!=j && f-1!=j){ //不是相鄰的數
					dp[i][j] += dp[i-1][f];
					dp[i][j] %= mod; 
				} 
			} 
		} 
	}
	for(int j=1;j<k;j++){			//	去掉第一位為0的k好數 
		sum += dp[l][j] ;
		sum %= mod;
	} 
	cout<<sum;
	return 0;
}