题意
这个里程表当走到3或8的时候就会跳过 给我们这个里程表上显示的数字
让我们求这个里程表的真实数据是多少
分析
由于 3 和 8 不存在 那么就相当于一个八进制数 但是这个八进制中3 是写作4 8是写作9
那么就好写了 也就是把数入的“特别八进制数”转化成一个十进制数
还有一个方法就是推每一位具体是少了多少个数
做题的时候一开始想往数位dp上想
结果Z犇一下就想到了递推 !!
通过对输入数据的每一位进行递推 看看到底少了多少个数
比如当推导数位长度等于2 时 少了:
C(2,1)∗10+(10−2)∗2=36
前面的是当首位是3或8 的时候 后面一位有10种情况 后面的是 当首位非3,8 有8种情况后面一位或3或8
比如当长度为3的时候 :
C(2,1)∗10∗10+(10−2)∗num[两位的情况]
这里也就相当于递推了
code
八进制:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
while(scanf("%d",&n),n){
int tmp = n,sum,p;
p=1;
sum=0;
while(tmp){
int b = tmp%10;
if(b>8)b-=2;
else if(b>3)b-=1;
sum+=b*p;
p*=8;
tmp/=10;
}
cout<<n<<": "<<sum<<endl;
}
return 0;
}
递推:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t[11];
ll pow(ll a,ll b){
ll ans = 1;
while(b){
if(b&1)ans*=a;
a*=a;
b>>=1;
}
return ans;
}
int main()
{
int n;
t[0]=0,t[1]=2;
for(int i=2;i<=9;i++){
t[i] = pow(10,i-1)*2 + 8*t[i-1];
}
while(scanf("%d",&n),n)
{
vector<int>ans;
int tmp = n;
while(tmp){
ans.push_back(tmp%10);
tmp/=10;
}
int cnt=0;
for(int i=ans.size()-1;i>0;i--)
{
if(ans[i]){
if(ans[i]>3&&ans[i]<8)ans[i]-=1,cnt+=pow(10,i);
else if(ans[i]>7&&ans[i]<10)ans[i]-=2,cnt+=2*pow(10,i);
cnt+=ans[i]*t[i];
}
}
if(ans[0]){
if(ans[0]>3&&ans[0]<8)cnt++;
else if(ans[0]>8&&ans[0]<10)cnt+=2;
}
printf("%d: %d\n",n,n-cnt);
}
return 0;
}