Time Limit:2000MS Memory Limit:16384KB 64bit IO Format:%I64d & %I64u
Description
Let’s consider
K-based numbers, containing exactly
N digits. We define a number to be valid if its
K-based notation doesn’t contain two successive zeros. For example:
- 1010230 is a valid 7-digit number;
- 1000198 is not a valid number;
- 0001235 is not a 7-digit number, it is a 4-digit number.
Given two numbers
N and
K, you are to calculate an amount of valid
K based numbers, containing
N digits.
You may assume that 2 ≤
K ≤ 10;
N ≥ 2;
N +
K ≤ 1800.
Input
The numbers
N and
K in decimal notation separated by the line break.
Output
The result in decimal notation.
Sample Input
input | output |
---|---|
2 10 | 90 |
题目大意:给两个数N和K,假设N表示为N格子,K指每个格子可以放(0—K-1)中的一个,但是不能存在相邻的格子都为0,开头的第一个格子不能为0. 求有多少种情况并输出。
分析:因为N较大,所以需要高精度运算,放入数组储存各位数。存在一个递推式d[i]=(k-1)*(d[i-1]+d[i-2]),
i个格子的所有情况分为两类,一类为第i-1个格子为0,有(k-1)*d[i-2]种情况; 第二类为第i-1个格子不为0,有(k-1)*d[i-1]种情况。 该题用一个二维数组储存情况数。
代码:
#include <stdio.h>
#include <string.h>
int dp[1800][3200];
int len[1800];//储存i位数的长度
int max(int x,int y)
{
if(x<=y)
return y;
return x;
}
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
memset(dp,0,sizeof(dp));
dp[1][0]=(k-1);
dp[2][0]=k*(k-1);
len[1]=len[2]=1;
if(n<=2)
{
printf("%d\n",dp[n][0]);
continue;
}
for(int i=3;i<=n;i++)
{
int len1=max(len[i-1],len[i-2]);
for(int j=0;j<len1;j++)//各位数相加
{
dp[i][j]+=(k-1)*(dp[i-1][j]+dp[i-2][j]);
if(dp[i][j]>=10)
{
dp[i][j+1]+=dp[i][j]/10;
dp[i][j]=dp[i][j]%10;
}
}
while(dp[i][len1])//将各个数储存在数组中
{
dp[i][len1+1]+=dp[i][len1]/10;
dp[i][len1]=dp[i][len1]%10;
len1++;
}
len[i]=len1;
}
for(int i=len[n]-1;i>=0;i--)
printf("%d",dp[n][i]);
printf("\n");
}
return 0;
}