实在是太恶心了这种个东西,忍不住吐槽,debug一小时
如果暴力只能得24,测试点7是过不去的,因为这个数字应该是超过int了,一定要开long long,不开long long要你狗命!!!
暴力解(24分)
#include <bits/stdc++.h>
using namespace std;
using ll =long long;
const int N = 2007;
map<char,int>mp;//标记对应的字符对应数字
int a[107],b[107];//两个数组用来存储每个位置对应的数字
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for(int i=0;i<=9;i++)mp[i+'0']=i;
for(int i=0;i<=25;i++)mp[i+'a']=10+i;
//赋值
string n1,n2;
int tag,ra;
cin>>n1>>n2>>tag>>ra;
if(tag==1)
{
//如果是1,那么就交换字符串位置,简便过程
string n;
n=n1;
n1=n2;
n2=n;
}
//反转字符串,好进行按位取
reverse(n1.begin(),n1.end());
reverse(n2.begin(),n2.end());
int mx=-1;
for(int i=0;i<n1.size();i++)
{
a[i]=mp[n1[i]];
mx=max(mx,a[i]+1);//寻找一开始从多少进制开始,因为一个字符串中进制必须比最大的字符对应数字还要大。
}
mx=max(mx,2);//如果只有01,那么必须比较2
ll sum=0,k=1;
for(int i=0;i<n2.size();i++)
{
b[i]=mp[n2[i]];
sum+=k*b[i];
k*=ra;
}
//计算我需要确定的值
//从最低开始向上枚举,因为比方说我只有一个10,那么显而易见,我必须拥有比确定值更大的进制才行
for(ll i=mx;i<=sum+1;i++)
{
ll t=1,s1=0;
for(int j=0;j<n1.size();j++)
{
s1+=t*a[j];
if(s1>sum||s1<0)
{
//枚举时候,如果出现中途发生的大于情况就说明你已经过了,没有找到;
//还有一种可能就是会出现超过ll的范围,直接出现负数
cout<<"Impossible";
return 0;
}
t*=i;
}
if(s1==sum)
{
//每次加完进行判断,只可能出现小于等于情况,小于不考虑,但是一旦出现等于那就直接输出
cout<<i;
return 0;
}
}
//可能到最后也找不到,那肯定就没有
cout<<"Impossible";
return 0;
}
卡的点其实就在于sum+1,实在是太大了,超时了,粗略来看应该是过大然后n1只出现较小字符。
使用二分查找可以有效降低时间复杂度,意义上就是优化暴力
#include <bits/stdc++.h>
using namespace std;
using ll =long long;
const int N = 2007;
map<char,int>mp;//标记对应的字符对应数字
int a[107],b[107];//两个数组用来存储每个位置对应的数字
int check(ll k,ll p)
{
//调用本函数的意义其实根暴力做法一样,只是增加一个对应数字返还的问题,需要不同情况返还不同数字
ll sum=0,t=1;
for(int i=0;i<n1.size();i++)
{
sum+=a[i]*t;
if(sum>p||sum<0)return 2;
t*=k;
}
if(sum==p)return 1;
else return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for(int i=0;i<=9;i++)mp[i+'0']=i;
for(int i=0;i<=25;i++)mp[i+'a']=10+i;
//赋值
string n1,n2;
int tag,ra;
cin>>n1>>n2>>tag>>ra;
if(tag==1)
{
//如果是1,那么就交换字符串位置,简便过程
string n;
n=n1;
n1=n2;
n2=n;
}
//反转字符串,好进行按位取
reverse(n1.begin(),n1.end());
reverse(n2.begin(),n2.end());
int mx=-1;
for(int i=0;i<n1.size();i++)
{
a[i]=mp[n1[i]];
mx=max(mx,a[i]+1);//寻找一开始从多少进制开始,因为一个字符串中进制必须比最大的字符对应数字还要大。
}
mx=max(mx,2);//如果只有01,那么必须比较2
ll sum=0,k=1;
for(int i=0;i<n2.size();i++)
{
b[i]=mp[n2[i]];
sum+=k*b[i];
k*=ra;
}
//计算我需要确定的值
//从最低开始向上枚举,因为比方说我只有一个10,那么显而易见,我必须拥有比确定值更大的进制才行
ll head=1LL*mx,tail=sum+1,ans=0;
while(head<=tail)
{
ll mid=(tail-head)/2+head;//一种非常新奇的写法,虽然我也不知道有什么用,偷了哈哈
int c=check(mid,sum);
if(c==0)
{
head=mid+1;
}
else
{
if(c==1)
{
ans=mid;
}
tail=mid-1;
}
}
if(!ans)cout<<"Impossible";
else cout<<ans;
return 0;
}