Ability To Convert(模拟+贪心思想(仅仅是思想))

时间:2022-12-16 22:08:24

【题目来源】http://codeforces.com/problemset/problem/758/D
【题意】
根据16进制的11311可以转化为十进制的475,过程是:
475 = 1·162 + 13·161 + 11·160
然后给出一个进制,再给出一个数,问,此进制下的这个数按这种方法转化为十进制的值是多少?
【思路】
看上面的那个式子,每次选的数字(例如:11,13,1)都是小于进制(例如16)的,也就是说,要尽可能的使得得到的最终结果最小,那么就要用到贪心的思想,也就是每次取到不能取为止。
然后,就是这道题的特色了:“0”的处理
比如1000 10001,那么这个结果是多少呢?是100000001。
而转换成代码呢就应该是这样的描述:
先判断1是否可取,可取,(倒着来),判断0是否可取,可取,再取0,直到取到左边第一个0,会发现,所取的这几个数字的长度(此时对应的是10000)已经大于进制,那么一定不可能,所以,丢掉后面所有不为0的数字,能丢几位丢几位,只剩下三个0,长度为3,此时再取1,但是发现此时的数字拼凑起来刚好是1000,等于进制,所以,只好去掉一个0,得到100,然后写出式子:1*1+0*1000+100*1000*1000;
【代码】

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
typedef long long LL;
const int INF=1e9;
char string_con[70];
int n;
int main()
{
while(~scanf("%d",&n))
{
getchar();
scanf("%s",string_con);
int len_con=strlen(string_con);
int i=len_con-1;
LL mid=1,ans=0,tmp=1,when=0;
int flag=0;
while(i>=0)
{
if(!flag) mid=1;//可以看成是记录当前数字位数,每次乘10
flag=0;
int j=i;
when=0;//当前结果
while(j>=0)
{
if(mid>=n)
{

flag=1;
break;
}
if(when+(string_con[j]-'0')*mid>=n)
{
if((mid/10)>when&&i!=j)//i!=j是为了让000能加上一个1再进行处理
flag=1;
break;
}
when+=(string_con[j]-'0')*mid;
mid*=10;
j--;
}
ans+=when*tmp;
if(flag)
{
if(when==0)//是为了刚才那个样例的特殊情况000(此时还没有1)
{
mid/=10;//去掉一个0,然后下一步去加上数字1
}
else
{
while(when)//能丢几个丢几个,反正小于进制
{
when/=10;
mid/=10;
}
}
}
tmp*=n;//进制每次乘本身
i=j;
}
printf("%lld\n",ans);
}
}