Acdream sgx和路飞(二分搜索)

考虑二分搜索,并且二分是判断左到中间那个数是否存在,所以只要判断1到n和为m的最大数是否相同。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int x[21],s[21],y[21];
int  vv(long long n){
    int p;
    p=0;
    while(n>0){
        if(p==0){
            s[0]=n%10;
        }
        else{
            s[p]=s[p-1]+n%10;
        }
        x[p++]=n%10;
        n=n/10;
    }
    return p;
}
long long solve(long long m,int n){
    int i,j,p;
    long long v,u;
    p=vv(m);
    if(s[p-1]>=n){
    for(i=p-1;i>=0;i--){
        if(n==0){
            y[i]=0;continue;
        }
        if(x[i]>=n){
            y[i]=n;
            n=0;
            continue;
        }
        y[i]=x[i];
        n=n-x[i];
    }
        v=0;u=1;
        for(i=0;i<p;i++){
            v+=u*y[i];
            u=u*10;
        }
        return v;
    }
    for(i=p-1;i>=0;i--){
        if(x[i]==0) continue;
        if(s[p-1]-s[i]+x[i]-1+9*i<n){
            break;
        }
    }
    if(i==p-1) return -1;
    while(i+1<=p-1&&x[i+1]==0)
        i++;
    for(j=p-1;j>i+1;j--){
        y[j]=x[j];
        n=n-x[j];
    }
    y[i+1]=x[i+1]-1;
    n=n-y[i+1];
    for(j=i;i>=0;j--){
        if(n>=9){
            n=n-9;
            y[i]=9;
        }
        else{
            break;
        }
    }
    if(j>=0){
        y[j]=n;
    }
    j--;
    for(;j>=0;j--)
        y[j]=0;
    u=0;
    v=1;
    for(i=0;i<p;i++){
        u+=v*y[i];
        v=v*10;
    }
    return u;
}
long long get( long long a, long long b ,int n){
     long long le,ri,mid;
    le=a;
    ri=b;
    while(le<=ri){
        mid=(le+ri)/2;
        if(solve(mid,n)-solve(le-1,n)==0){
            le=mid+1;
        }
        else{
            ri=mid-1;
        }
    }
    return le;
}
int main()
{
    int n;
    long long a,b;
    while(scanf("%lld%lld%d",&a,&b,&n)!=EOF){
        printf("%lld\n",get(a,b,n));
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值