2035: [蓝桥杯2022初赛] X进制减法
内存限制:256 MB 时间限制:1 S 标准输入输出
题目类型:传统 评测方式:文本比较 上传者:外部导入
提交:352 通过:72
题目描述
进制规定了数字在数位上逢几进一。
X 进制是一种很神奇的进制,因为其每一数位的进制并不固定!
例如说某种X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制:
则 X 进制数321 转换为十进制数为65。65=3*(2*10)+2*(2)+1*(1)。
现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确定。
只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进制。
请你算出 A − B 的结果最小可能是多少。
请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数字要小于其进制。
输入格式
第一行一个正整数 N,含义如题面所述。
第二行一个正整数 Ma,表示 X 进制数 A 的位数。
第三行 Ma 个用空格分开的整数,表示 X 进制数 A 按从高位到低位顺序各个数位上的数字在十进制下的表示。
第四行一个正整数 Mb,表示 X 进制数 B 的位数。
第五行 Mb 个用空格分开的整数,表示 X 进制数 B 按从高位到低位顺序各个数位上的数字在十进制下的表示。
请注意,输入中的所有数字都是十进制的。
30%的测试数据:2≤N≤10,1≤Ma,Mb≤8。
100%的测试数据:2≤N≤1000,1≤Ma,Mb≤100000,B≤A。
输出格式
输出一行一个整数,表示X 进制数A − B 的结果的最小可能值转换为十进制后再模1000000007 的结果。
输入样例 复制
11
3
10 4 0
3
1 2 0
输出样例 复制
94
数据范围与提示
当进制为:最低位 2 进制,第二数位 5 进制,第三数位 11 进制时,减法得到的差最小。
此时A 在十进制下是108,B 在十进制下是 14,差值是 94。
从B站up主“大雪菜”那儿弄懂的:
分析:贪心策略
证明:
A:An-1,An-2,...,A1,A0;
B:Bn-1,Bn-2,...,B1,b0;
X进制的各位进制数位Pn-1,Pn-2,...,P1,P0;
A=(An-1)*(Pn-2*Pn-3*...*P1*p0)+(An-2)*(Pn-3*Pn-4*...*P1*P0)+...+A1*P0+A0;
B=(Bn-1)*(Pn-2*Pn-3*...*P1*p0)+(Bn-2)*(Pn-3*Pn-4*...*P1*P0)+...+B1*P0+B0;
令Di=Ai-Bi;
则A-B=(Dn-1)*(Pn-2*Pn-3*...*P1*p0)+(Dn-2)*(Pn-3*Pn-4*...*P1*P0)+...+D1*P0+D0
=((Dn-1)*(Pn-2*...*Pk+1*Pk)+(Dn-2)*(Pn-3+...+Pk+1*Pk)+...+Dk)*(Pk-1*...*P1*P0)+...+D1*P0+D0;
因为(Pk-1*...*P1*P0)>0,所以判断((Dn-1)*(Pn-2*...*Pk+1*Pk)+(Dn-2)*(Pn-3+...+Pk+1*Pk)+...+Dk)的符号,
这个式子又是A与B的前k位数,想要A>B,那么必然要满足(Dn-1)*(Pn-2*...*Pk+1*Pk)+(Dn-2)*(Pn-3+...+Pk+1*Pk)+...+Dk)>0;
并且要答案数最小,那么想必Pk-1 的进制数取最小即可,但是最小也要大于等于2,即取max({A[i], B[i], 1}) + 1
为什么A与B都是n位,因为题目说了A>B,那么A的 位数必然大于等于B的位数,当B的位数小于A的时候,在B前面补0即可。
又根据秦九韶算法:
A-B=(((((((Dn-1*Pn-2)+Dn-2)*Pn-3)+Dn-3)*Pn-4)+...+D1)*P0+D0);
/**
A:An-1,An-2,...,A1,A0;
B:Bn-1,Bn-2,...,B1,b0;
X进制的各位进制数位Pn-1,Pn-2,...,P1,P0;
A=(An-1)*(Pn-2*Pn-3*...*P1*p0)+(An-2)*(Pn-3*Pn-4*...*P1*P0)+...+A1*P0+A0;
B=(Bn-1)*(Pn-2*Pn-3*...*P1*p0)+(Bn-2)*(Pn-3*Pn-4*...*P1*P0)+...+B1*P0+B0;
令Di=Ai-Bi;
则A-B=(Dn-1)*(Pn-2*Pn-3*...*P1*p0)+(Dn-2)*(Pn-3*Pn-4*...*P1*P0)+...+D1*P0+D0
=((Dn-1)*(Pn-2*...*Pk+1*Pk)+(Dn-2)*(Pn-3+...+Pk+1*Pk)+...+Dk)*(Pk-1*...*P1*P0)+...+D1*P0+D0;
因为(Pk-1*...*P1*P0)>0,所以判断((Dn-1)*(Pn-2*...*Pk+1*Pk)+(Dn-2)*(Pn-3+...+Pk+1*Pk)+...+Dk)的符号,
这个式子又是A与B的前k位数,想要A>B,那么必然要满足(Dn-1)*(Pn-2*...*Pk+1*Pk)+(Dn-2)*(Pn-3+...+Pk+1*Pk)+...+Dk)>0;
为什么A与B都是n位,因为题目说了A>B,那么A的 位数必然大于等于B的位数,当B的位数小于A的时候,在B前面
补0即可。
又根据秦九韶算法:
A-B=(((((((Dn-1*Pn-2)+Dn-2)*Pn-3)+Dn-3)*Pn-4)+...+D1)*P0+D0);
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000000007;
int main()
{
int n;
scanf("%d",&n);
int len1,len2;
cin >> len1;
int input1[len1],input2[len1];
memset(input1,0,sizeof(input1));
memset(input2,0,sizeof(input2));
for(int i=len1-1;i>=0;--i)
scanf("%d",&input1[i]);
cin >> len2;
for(int i=len2-1;i>=0;--i)
scanf("%d",&input2[i]);
long long result=0,forwar=1;
for(int i=len1-1;i>=0;--i)
{
// result=result*forwar+(input1[i]-input2[i]);
// result%=maxn;
// forwar=max(max(input1[i-1],input2[i-1])+1,2); // 虽然这里数组下标越界了,但是后面不会
// 用到这个数据
//更好的写法
result=(result*(max({input1[i],input2[i],1})+1)+input1[i]-input2[i])%maxn;
}
cout << result << endl;
return 0;
}
开始写的另一个代码,也是对的:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000000007;
int main()
{
int n;
scanf("%d",&n);
int len1,len2;
cin >> len1;
int input1[len1],input2[len1];
memset(input1,0,sizeof(input1));
memset(input2,0,sizeof(input2));
for(int i=0;i<len1;++i)
scanf("%d",&input1[i]);
cin >> len2;
for(int i=0;i<len2;++i)
scanf("%d",&input2[i]);
reverse(input1,input1+len1);
reverse(input2,input2+len2);
long long result=0,forwar=1;
for(int i=0;i<len1;++i)
{
/**这段代码也是对的,但下面那个更加简单
if(i==0)
{
result+=(input1[i]-input2[i]);
}
else
{
int r=max(max(input1[i-1],input2[i-1]),1);
forwar*=(r+1);
forwar%=maxn;
//cout << "try: " << forwar << endl;
result+=(input1[i]-input2[i])*forwar;
result%=maxn;
}*/
result+=(input1[i]-input2[i])*forwar;
result%=maxn;
int r=max(max(input1[i],input2[i])+1,2);
forwar*=r;
forwar%=maxn;
}
cout << result << endl;
return 0;
}