题目描述
进制规定了数字在数位上逢几进一。
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.
代码实现
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
//a[i]存储数A,b[i]存储数B,c[i]存储每一位的进制。
long long a[100005],b[100005],c[100005];
int main(){
long long N,Ma,Mb,ans=0,k=1;
int i;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
cin>>N;
cin>>Ma;
for(i=Ma;i>0;i--){
cin>>a[i];
}
cin>>Mb;
for(i=Mb;i>0;i--){
cin>>b[i];
}
for(i=Ma;i>0;i--){
c[i]=max(a[i],b[i])+1; //每一位的进制对应A和B中的最大数加一
if(c[i]<2)c[i]=2; //最低为二进制
}
for(i=1;i<=Ma;i++){ //A-B,用a[i]存储结果
if(a[i]>=b[i])a[i]=a[i]-b[i]; //A的第i位大于B的第i位时
else {
a[i]=a[i]+c[i]-b[i]; //A的第i位小于B的第i位时,向高位借一
a[i+1]-=1;
}
}
for(i=2;i<=Ma;i++){ //计算对应的十进制数
//第i位上的数对应的十进制是:a[i]乘以比其低位的每一进制
/*
比如:最低数位为二进制,第二数位为十进制,第三数位为八进制,则321转换为十进制数就是
3*2*10+2*2+1。
*/
k*=c[i-1];
k%=1000000007; //!!!不可省略!!!过程中的取余不可省略,否则只能通过30%的数据
ans+=a[i]*k;
ans%=1000000007; //!!!不可省略!!!过程中的取余不可省略,否则只能通过30%的数据
}
ans+=a[1]; //上面只加第二数位到最高数位,最后把最低数位加上
cout<<ans%1000000007;
return 0;
}