【问题标题】:Getting Overflow and TLE issues in this Atcoder question在这个 Atcoder 问题中出现溢出和 TLE 问题
【发布时间】:2021-03-06 17:29:18
【问题描述】:

我正在解决这个问题:D-Base n (https://atcoder.jp/contests/abc192/tasks/abc192_d)

它指出:

给定一个字符串 X 由 0 到 9 和一个整数组成 米 . 让 d 成为最大的数字 X . 不大于多少个不同的整数 米 可以通过选择一个整数来获得 n 不小于 d + 1 并且看到 X 作为基础—— n 号码?

我反复解决了这个问题(它给了我小输入的正确答案)但它给了我 TLE 和溢出问题(请参阅我在https://atcoder.jp/contests/abc192/submissions/20651499 提交的内容)。社论说我必须使用Binary Search,我已经实现如下。但我仍然没有得到正确的输出。欢迎任何建议。

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
int M;
bool getInBase(unsigned long long int x, int base){
    int i=0;
    unsigned long long int ans = 0;
    while(x>0){
        int temp = x%10;
        ans += pow(base,i)*temp;
        i++;
        x/=10;
        if(ans>M) return false;
    }
    return (ans<M);
}

int main(){
    string X;
    cin>>X;
    cin>>M;
    int mx = 0;
    unsigned long long orig =0;
    for(char x: X){
        int sum = (int) x - (int)'0';
        if(sum>mx) mx = sum;
        orig = orig*10 + ((int)x - (int) '0');
    }
    int ans=0;
    unsigned long long int l = mx+1, r =M+1;
    unsigned long long int mid;
    while(l<r){
        mid = (l+r)/2;
        if(getInBase(orig,mid)){
            l = mid +1;
        }
        else{
            r = mid-1;
        }
    }
    
    cout<<l-mx;

}

【问题讨论】:

  • 根据问题描述,数字X最多可以有60位。尝试将其存储在 unsigned long long 变量中是没有意义的。要么使用大整数库,要么找到不涉及将 60 位以 10 为基数的数字填充到 64 位整数中的解决方法。

标签: c++ algorithm data-structures binary-search


【解决方案1】:
ll convert(string x, ll base, ll m){
    ll ans=0;
    ll p=0;
    ll cur=1;
    for(int i=x.size()-1;i>=0;i--){
        if(cur<0 || ans<0)
            return m+1;
        ans+=(ll)(x[i]-'0')*cur;
        cur*=base;
        if(ans>m)
            return m+1;
    }
    return ans;
}
void solve(){
    ll i, j, m;
    string x;
    cin>>x>>m;
    int n=x.size();
    ll mx=0;
    for(auto i:x){
        mx=max(mx, (ll)(i-'0'));
    }
    if(n==1){
        cout<<(((ll)stoi(x))<=m)<<endl;
        return;
    }
    ll k=(ll)ceil(pow(m*1.0, 1.0/(n-1)));
    ll l=mx+1;
    ll r=k+1;
    ll ans=0;
    while(l<=r){
        ll mid=l+(r-l)/2;
        ll c=convert(x, mid, m);
        //cout<<"l = "<<l<<" mid ="<<mid<<" r= "<<r<<" c= "<<c<<endl;
        if(c<=m){
            ans=max(ans, mid);
            l=mid+1;
        }else{
            r=mid-1;
        }
    }
    cout<<max(0LL, ans-mx)<<endl;
}

【讨论】:

  • 我理解我的错误!谢谢@risingStark
  • 只是一个查询,你为什么取k = m^(1/(n-1))?
  • 给定的数字是一个 n 位数字。写出不带任何前导零的最小 n 位数。它将是 100000....0000(n 位)。现在,如果将其转换为任何基数 k,则 k ^(n-1) r = 1e18,代码仍然可以正常工作。
  • 聪明的方法。谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2011-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多