x进制减法-蓝桥杯(贪心)

进制规定了数字在数位上逢几进一。
X 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某
种 X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则X 进制数 321 转换为
十进制数为 65。
现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确
定,只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进制。
请你算出 A B 的结果最小可能是多少。
请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数字要小于其进制。
【输入格式】
第一行一个正整数 N,含义如题面所述。
第二行一个正整数 Ma,表示 X 进制数 A 的位数。
第三行 Ma 个用空格分开的整数,表示 X 进制数 A 按从高位到低位顺序各
个数位上的数字在十进制下的表示。
第四行一个正整数 Mb,表示 X 进制数 B 的位数。
第五行 Mb 个用空格分开的整数,表示 X 进制数 B 按从高位到低位顺序各
个数位上的数字在十进制下的表示。
请注意,输入中的所有数字都是十进制的。
【输出格式】
输出一行一个整数,表示 X 进制数 A B 的结果的最小可能值转换为十进
制后再模 1000000007 的结果。
【样例输入】
11
3
10 4 0
3
1 2 0
【样例输出】
94
【样例说明】
当进制为:最低位 2 进制,第二数位 5 进制,第三数位 11 进制时,减法
得到的差最小。此时 A 在十进制下是 108,B 在十进制下是 14,差值是 94。
【评测用例规模与约定】
对于 30% 的数据,N ≤ 10; Ma, Mb ≤ 8.
对于 100% 的数据,2 ≤ N ≤ 1000; 1 ≤ Ma, Mb ≤ 100000; A ≥ B.
 

本题最为难以理解的一步就是题目中的进制减法是怎个说法,以及题目中的321转为十进制后是65,它是怎么来的。当理解了这个之后,这道题基本上也就迎刃而解了

321是怎样转为十进制的65的:

首先,先用熟悉的十进制数来理解这个问题,

比如,十进制下的9     让9+1 成为10,是如何来的。

个位数是十进制,在个位上思考,9+1,就是10,并且因为是十进制,所以进一位,本位(即个位)为0,最终就是10(十位数为1,个位数为0)

那么将它带入本题:321,第一位是二进制,第二位是十进制,第三位是八进制,从0开始,则是0   1    2(因为第一位是二进制,所以逢二加一)->10    11   20(因为第二位是十进制,所以逢十加一,此时为2,无需进一)  ······    91    92(因为第一位是二进制,所以进一,个位为0,第二位9+1,因为第二位是十进制,则也需进一)->100  ···

理解之后,321如何转化为65,也就很好得出了,1(第一位数)+2(第二位数)*2(二进制)+3(第三位数)*2(二进制)*10(十进制)  = 1+4+60 = 65

接下来的就很好理解了,下面的将以题目给的样例为例子

两数相减的最小数,先将两个数相减,随后再确定每位的进制   A:10  4   0     B:1  2  0

对应位数A-B,则结果为 C:9  2   0

我们此时需要的仅为,让C的结果最小,如何让C的结果最小,C的每一位数已经确定,无法更改,那么我们只有在进制方面最小,则结果就为最小。并且注意A和B均要合法,所以每一位的进制,就是此位上两个数的最大值+1      A和B:第三位数的最大值为10,则为11进制,第二位数最大值为4,则为5进制,第一位数的最大值为0,则为2进制

当C中的某一位数为负数时,此推论也成立,(可以想象,比如   7  -1,要想第一位的数大于0,则需要第二位减一,第一位加上第一位的进制数,我们需要它最小,那么就是进制最小的情况)

下面则是我写的代码

#include <bits/stdc++.h>

using namespace std;

const int mod = 1000000007;

int N;

int Ma,Mb;

int a[100000],b[100000];

long long jinzhi[1000000];//若此处不为long long 类型,则只能获得30分,此处的进制,不是本位的进制,是前缀和

int main(){

    cin>>N;

    cin>>Ma;

    for(int i=Ma-1;i>=0;i--){

        cin>>a[i];

    }

    cin>>Mb;

    for(int i=Mb-1;i>=0;i--){

        cin>>b[i];

    }

    int n = max(Ma,Mb);

    jinzhi[0] = 1;

    for(int i=0;i<n;i++){

        int maxn = max(a[i],b[i]);

        if(maxn==0){

            jinzhi[i] = 2;

        }else{

            jinzhi[i] = maxn+1;

        }

        if(i>0)

        jinzhi[i] = (jinzhi[i]*jinzhi[i-1])%mod;

    }

    long long ans = a[0]-b[0];

    for(int i=1;i<n;i++){

        ans= (ans+ ((a[i]-b[i])*jinzhi[i-1]))%mod;//当前位乘前一位的进制

    }

    ans %= mod;

    cout<<ans<<endl;

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值