ICPC North America Qualifier Contest 2015 A題 All about that base【模擬進制轉換,注意細節】

題目鏈接:https://nanti.jisuanke.com/t/44105

題意

題意就是給你一些四則運算的等式,等式的格式是 x op y = z,其中x,y,z都是字符串,表示某個進制下的數字,op是運算符,包括+,-,*,/。

現在有1~36進制可供選擇,你需要找到某個進制使得等式成立,輸出滿足等式的所有進制,找不到就輸出invalid。

其中,1~9進制用數字1-9表示,10~35進制用字母a-z表示,36進制用0來表示。注意,在等式中的0還是表示0,不是表示36。

同時,在任意進制下,等式中的三個數字轉換成十進制後必須在[1,232-1]區間內。

思路

題意也算比較好懂,基本上一看就知道是模擬,因爲實際上就是進制轉換(這剛學C語言就會做?),數據量也比較小。模擬也不見得就很好寫,有很多細節要注意。

  1. 在等式中的0還是表示0,不是表示36;在輸出進制時,若要表示爲36進制,則輸出0。
  2. 特判,要特別注意一進制! 本來一進制應該只包含0,但是題目規定一進制用1代替0,也就是說在本題中,一進制只能包含1,比如等式11 - 10 = 1,在一進制下就不成立,因爲10包含了0。
  3. inf=(1<<32)-1,這肯定是錯的,因爲1默認是int,1<<32直接爆int,所以要寫成(1ll<<32)-1。1ll等價於(long long)1,也就是必須要先把1強制轉換一下。

因爲第二點,wa了無數次,也是教訓。

爲什麼說在本題中,一進制只能包含1,看一下題目描述:
在這裏插入圖片描述
在這裏插入圖片描述

AC代碼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+10,inf=(1ll<<32)-1;//記得寫1ll轉換成long long,這裏容易錯
ll T;
char a[N],b[N],c[N];
ll to_ll(char x)
{
    if(x>='1'&&x<='9')return x-'0';
    else if(x>='a'&&x<='z')return x-'a'+10;
    else return 0;
}
ll to_char(ll x)
{
    if(x>=1&&x<=9)return x+'0';
    else if(x>=10&&x<=35)return x+'a'-10;
    else return '0';
}
ll get_sum(char s[],ll bas)//將字符串轉換成bas進制下的數值
{
    ll n=strlen(s);
    ll ans=0;
    ll tmp=1;
    for(ll i=n-1;i>=0;i--)
    {
        if(tmp<0||tmp>inf||ans>inf||ans<0)return -1;
        ll x=to_ll(s[i]);
        //printf("x=%lld s[i]=%c\n",x,s[i]);
        ans+=x*tmp;//tmp是bas的次方
        tmp*=bas;
    }
    return ans;
}
ll get_mx(char s[])//得到字符串中最大的單個數字
{
    ll n=strlen(s);
    ll mx=0;
    for(ll i=0;i<n;i++)
    {
        ll x=to_ll(s[i]);
        mx=max(mx,x);
    }
    return mx;
}
bool have0(char s[])//判斷字符串中是否有0
{
    for(int i=0;s[i];i++)
    {
        if(s[i]=='0')return 1;
    }
    return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--)
    {
        char opt,dengyu;
        cin>>a>>opt>>b>>dengyu>>c;
        //printf("a=%s opt=%c b=%s dengyu=%c c=%s\n",a,opt,b,dengyu,c);
        ll mx1=get_mx(a);
        ll mx2=get_mx(b);
        ll mx3=get_mx(c);
        ll mx=max(max(mx1,mx2),mx3);
        //printf("mx=%lld\n",mx);
        if(opt=='+')
        {
            bool flag=0;
            ll i;
            for(mx==1?i=mx:i=mx+1;i<=36;i++)//遍歷可能的進制
            {
                ll s1=get_sum(a,i);
                ll s2=get_sum(b,i);
                ll s3=get_sum(c,i);
                //printf("i=%lld %lld+%lld=%lld\n",i,s1,s2,s3);
                if(!(s1>=1&&s1<=inf&&s2>=1&&s2<=inf&&s3>=1&&s3<=inf))continue;//滿足題目範圍
                if(i==1&&(have0(a)||have0(b)||have0(c)))continue;//一進制不能包含0
                if(s1+s2==s3)
                {
                    flag=1;
                    printf("%c",to_char(i));
                }
            }
            if(flag)printf("\n");
            else printf("invalid\n");
        }
        else if(opt=='-')
        {
            bool flag=0;
            ll i;
            for(mx==1?i=mx:i=mx+1;i<=36;i++)
            {
                ll s1=get_sum(a,i);
                ll s2=get_sum(b,i);
                ll s3=get_sum(c,i);
                if(!(s1>=1&&s1<=inf&&s2>=1&&s2<=inf&&s3>=1&&s3<=inf))continue;
                if(i==1&&(have0(a)||have0(b)||have0(c)))continue;//一進制不能包含0
                if(s1-s2==s3)
                {
                    flag=1;
                    printf("%c",to_char(i));
                }
            }
            if(flag)printf("\n");
            else printf("invalid\n");
        }
        else if(opt=='*')
        {
            bool flag=0;
            ll i;
            for(mx==1?i=mx:i=mx+1;i<=36;i++)
            {
                ll s1=get_sum(a,i);
                ll s2=get_sum(b,i);
                ll s3=get_sum(c,i);
                if(!(s1>=1&&s1<=inf&&s2>=1&&s2<=inf&&s3>=1&&s3<=inf))continue;
                if(i==1&&(have0(a)||have0(b)||have0(c)))continue;//一進制不能包含0
                if(s1*s2==s3)
                {
                    flag=1;
                    printf("%c",to_char(i));
                }
            }
            if(flag)printf("\n");
            else printf("invalid\n");
        }
        else if(opt=='/')
        {
            bool flag=0;
            ll i;
            for(mx==1?i=mx:i=mx+1;i<=36;i++)
            {
                ll s1=get_sum(a,i);
                ll s2=get_sum(b,i);
                ll s3=get_sum(c,i);
                if(!(s1>=1&&s1<=inf&&s2>=1&&s2<=inf&&s3>=1&&s3<=inf))continue;
                if(i==1&&(have0(a)||have0(b)||have0(c)))continue;//一進制不能包含0
                if(s1%s2==0&&s1/s2==s3)
                {
                    flag=1;
                    printf("%c",to_char(i));
                }
            }
            if(flag)printf("\n");
            else printf("invalid\n");
        }
    }
    return 0;
}
/*
1
11 - 10 = 1

ans:23456789abcdefghijklmnopqrstuvwxyz0

1
1 + 1 = 2
ans:3456789abcdefghijklmnopqrstuvwxyz0
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章