Historical Maths(二分判断进制)

题目描述

传送门

2 2 0
1 2
3 1 0 0
Output
4
Input 复制
3 5 1 2
2 11 3
5 4 5 1 12 6
Output
13
Input 复制
2 3 2
2 3 2
3 10 12 4
Output
impossible

题目大意:就是给你一组数组A,数组B,数组C。然后问你是否有一个k,就是使得k进制下A数组变成10进制数a,和k进制下B数组变成10进制数b,和k进制下的C数组变成的数c

使得a*b==c,求这个k

题目大意

需要观察出进制与 A * B 和 C 的大小之间具有单调性,如果进制较小的话,那么进位自然就会变多,从而使得位数边长,整体数字就会变大,反之亦然,所以据此,可以直接二分答案,用一个 check 进行检查,需要注意的是答案会爆 long long,所以整体用 __int128 进行计算即可,二分的下限设置为所有数字的最大值 + 1,上限设置为 1e20

 

首先这个题的下限要设成所有数的最大值+1,例如10进制下最大值是9。或者求完之后再判断一下

这个是用二分的位数判断的,如果位数大的话,就增大进制,小的话就减小进制,如果相等的话就从大到小看看第一个不同的数,如果大的话就增大进制,变小要减小进制

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef __int128 ll;
const int maxn=2e6+100;
const int N=1e3+100;
inline __int128 read()
{
    __int128 x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
    if(ch=='-')
    f=-1;
    ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
    x=x*10+ch-'0';
    ch=getchar();
    }
    return x*f;
}
inline void write(__int128 x)
{
    if(x<0)
    {
    putchar('-');
    x=-x;
    }
    if(x>9)
    write(x/10);
    putchar(x%10+'0');
}

ll x[N];
ll y[N];
ll z[N];
ll res[maxn];
ll ans[maxn];
int n,m,k;
ll ma=0;
int judge(ll mid){
    ll yu=0;
    int pos;
    for(pos=0;;pos++){
        if((ans[pos]+yu)==0&&pos>=n+m-2){
            break;
        }
        res[pos]=(ans[pos]+yu)%mid;
        yu=(ans[pos]+yu)/mid;
        //cout<<res[pos]<<" "<<yu<<endl;
    }
//    cout<<mid<<" "<<pos<<endl;
    if(pos==k){
        for(int i=pos-1;i>=0;i--){//一定要从大到小 
        //    cout<<res[i]<<endl;
            if(z[i]<res[i]){
                return pos+2; 
            }
            else if(z[i]>res[i]){
                return pos-2;
            }
        }
        return -1; 
    }
    return pos;
}
int main(){
    cin>>n;
    for(int i=n-1;i>=0;i--){
        x[i]=read();
        //scanf("%lld",&x[i]);
        ma=max(ma,x[i]);
    }
    cin>>m;
    for(int i=m-1;i>=0;i--){
        y[i]=read();
        //scanf("%lld",&y[i]);
        ma=max(ma,y[i]);
    } 
    cin>>k;
    for(int i=k-1;i>=0;i--){
        z[i]=read();
        //scanf("%lld",&z[i]);
        ma=max(ma,z[i]);
    }
    for(int i=0;i<=n-1;i++){
        for(int j=0;j<=m-1;j++){
            ans[i+j]+=1ll*(x[i]*y[j]);
        }
    }
    //judge(4);
    /*
    for(int i=0;i<=n+m-2;i++){
        cout<<ans[i]<<endl;
    }
    //*/
    
        ll l=2,r=1e22,ans;
        while(r>=l){
            ll mid=(l+r)/2;
            if(judge(mid)==-1){
                if(mid<=ma){
                    cout<<"impossible"<<"\n";
                    return 0; 
                }
                write(mid);
                //cout<<mid<<"\n";
                return 0;
            } 
            if(judge(mid)<k){
                r=mid-1;
            }
            else{
                l=mid+1;
            }
        }
        cout<<"impossible"<<"\n";
    
}

 

posted @ 2021-09-13 00:40  lipu123  阅读(49)  评论(0)    收藏  举报