正题
大意
如果一个数每一位都小于k那么这个数是好数。给出n和k,求1-n里有多少个好数。
解题思路1
将起改为一个k+1进制的数,那么每次加1后这个数都是好数。然后判断一下是否大于n(十进制的情况下)
解题思路2
数位dp,时间复杂度O(n的位数):
f[i]表示后i位数没有被前面的数影响的好数数量
g[i]表示后i位数被前面的数影响的好数数量
n[i]表示n的第i位数
然后动态转移方程
f[i]=f[i−1]∗(k+1)f[i]=f[i−1]∗(k+1)
g[i]=f[i](n[i]>k)g[i]=f[i](n[i]>k)
g[i]=g[i−1]+f[i−1]∗n[i](n[i]<=k)g[i]=g[i−1]+f[i−1]∗n[i](n[i]<=k)
代码1
#include<cstdio>
using namespace std;
int a[9],maxs[9],w,m,s,n;
bool add()
{bool flag=0;a[1]++;//加1for (int i=1;i<=w;i++){if (a[i]>m){a[i+1]++;a[i]=0;//进位}if (a[i]>maxs[i]) flag=true;else if (a[i]<maxs[i]) flag=false;//判断大小}if (a[w+1]!=0) return true;return flag;
}
int main()
{ scanf("%d%d",&n,&m);a[1]=0;for (int i=n;i;i/=10){maxs[++w]=i%10;//计算}while (true){if (add()) break;s++;}printf("%d",s);
}
代码2
#include<cstdio>
using namespace std;
int n,num,g,f,k;
int main()
{scanf("%d%d",&n,&k);f=1;g=1;for (n=n;n;n/=10){num=n%10;if (num>k) g=(k+1)*f;else g+=num*f;f=(k+1)*f;//动态转移}printf("%d",g-1);
}