K-进制数
考虑包含N位数字的K-进制数. 定义一个数有效, 如果其K-进制表示不包含两连续的0.
例:
1010230 是有效的7位数
1000198 无效
0001235 不是7位数, 而是4位数.
给定两个数N和K, 要求计算包含N位数字的有效K-进制数的总数.
假设2 <= K <= 10; 2 <= N; 4 <= N+K <= 18.
两个十进制整数N和K
十进制表示的结果
2
10
90
拿到这个题看了一眼范围,暴力应该会被T,但是我还是试了一发,结果被T的一发不可收拾!可是不暴力的话应该怎么做呢?
其实这是一个递推的问题:
我们先看N=1的情况,显然有 k-1 种情况符合条件,只有一种条件不符合情况,因为第一位为0 是不对的,我们记 AC1=k-1,WA1=1;
当N=2的时候,需要和N=1的情况相联系,第二位的选项还是k-1种,满足条件的情况分为两部分,一部分是第一位满足情况 k-1种,以及第一位不满足的情况,所以AC2=(k-1)*(AC1+WA1);不满足条件的情况就发生了改变,即在AC1 前面补0的情况,当然00必定不符合情况,以后也无法凑成满足条件的,所以我们不需要考虑,即 WA2=AC1
当N=3时,还是需要看N=2的情况,第三位的选项有 k-1种,因为第三位不会取到0,而也不会有00的情况,所以第三位仍然可以与AC2和WA2想匹配,即AC3=(k-1)*(AC2+WA2);不满足的情况仍然是在AC2的前面补0,即 WA3=AC2
所以递推式就出来喽,AC=(k-1)*(preAC+WA); WA=preAC;我们求得最终的AC就可以AC了
代码很简单 :
#include<cstdio>
#include<string>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int _read() {
char ch = getchar();
int sum = 0;
while (!(ch >= '0' && ch <= '9'))ch = getchar();
while (ch >= '0' && ch <= '9')sum = sum * 10 + ch - 48, ch = getchar();
return sum;
}
const int inf=0x3f3f3f3f;
const int mm=0;
int main()
{
int n,k;
cin>>n>>k;
int ac=k-1,wa=1;
for(int i=2;i<=n;i++){
int pre=ac;
ac=(k-1)*(ac+wa);// 前面补非零*(上一个可以的+前面为0的)
wa=pre;//前补零的
}
cout<<ac<<endl;
return 0;
}