B. 莲子的机械动力学
【具象化题意】
备注:具象化题意和抽象化题意完全等价,可以只选择其中一
份进行阅读。
专攻超统一物理学的莲子,对机械结构的运动颇有了解。如下
图所示,是一个三进制加法计算器的(超简化)示意图。
一个四位的三进制整数,从低到高位,标为 𝑥1, 𝑥2, 𝑥3, 𝑥4。换
言之,这个数可以写成 𝑥4𝑥3𝑥2𝑥1(3)。把它放在这四个齿轮里,对
应箭头指向的数字就是现在这位的数值。
在这种机械式计算机里,我们通过齿轮的啮合来实现数位间的
连接。通过不同齿轮半径的比例来确定进制。图中所有浅灰色的小
齿轮的半径,比上使用皮带相接的较大齿轮的半径,都是 1: 3。那
么小齿轮每转动一圈,大齿轮就转动 1
3 圈,也就是刚好一个数码
的角度。
于是,我们通过控制齿轮的半径实现了 3 进制的进位。
如果需要实现三进制加法,则只需要在对应数位拨动对应的数
码长度即可。
如下是个例子,实现 1021(3) + 0021(3) = 1112(3)
初始时齿轮的状态如上
把第一个齿轮拨动一个单位长度,变为如上图所示。
把第二个齿轮拨动两个单位长度,变为如上图所示。读数,得
到结果 1112(3)。
现在莲子设计了如下图所示的机械结构。对于从左往右数的第
𝑖 枚齿轮,它上面的浅色小齿轮与第 𝑖 + 1 枚齿轮上的深色小齿轮
的半径之比为 1: (𝑖 + 2)。也就是说,第 𝑖 枚齿轮每转动 1 圈,
第 𝑖 + 1 枚齿轮转过的角度恰好为它上面的一个数码。
莲子想要知道,在这样的特别的进制表示下,给定 𝑎, 𝑏,那么
计算出的 𝑎 + 𝑏 的结果是多少。
【抽象化题意】
给定两个长度分别为 𝑛, 𝑚 的整数 𝑎, 𝑏,计算它们的和。
但是要注意的是,这里的 𝑎, 𝑏 采用了某种特殊的进制表示法。
最终的结果也会采用该种表示法。具体而言,从低位往高位数起,
第 𝑖 位采用的是 𝑖 + 1 进制。换言之,相较于十进制下每一位的
「逢 10 进 1」,该种进制下第 𝑖 位是「逢 𝑖 + 1 进 1」。
下图所示,左边是十进制的竖式加法;右边是这种特殊进制的
竖式加法。图中的红色加号表示上一位发生了进位。
输入格式
第一行有两个整数 𝑛, 𝑚,分别表示 𝑎 和 𝑏 的位数。
第二行有 𝑛 个整数,中间用空格隔开,从高到低位描述 𝑎 的
每个数码。
第三行有 𝑚 个整数,中间用空格隔开,从高到低位描述 𝑏 的
每个数码。
输出格式
输出有若干个整数,从高到低位输出 𝑎 + 𝑏 在这种特殊表示
法下的结果。
输入样例 1 输出样例 1
5 4 4 2 1 1 0
3 3 2 1 1
3 2 2 1
输入样例 2 输出样例 2
10 1 10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
0
数据规模
对于全部数据,保证 1 ≤ 𝑛, 𝑚 ≤ 2 × 10^5,从低位往高位数起
有 𝑎𝑖 ∈ [0, 𝑖],𝑏𝑖 ∈ [0, 𝑖]。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5+10;
LL a[N],b[N],ans[N];
void solve(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int j=1;j<=m;j++) scanf("%lld",&b[j]);
LL tt = 2,t = 0;
int i,j;
for(i=n,j=m;i>0&&j>0;i--,j--){
t += a[i] + b[j];
ans[tt] = t % tt;
t /= tt;
tt++;
}
while(i>0){
t += a[i];
ans[tt] = t % tt;
t /= tt;
tt++;
i--;
}
while(j>0){
t += b[j];
ans[tt] = t % tt;
t /= tt;
tt++;
j--;
}
if(t > 0) ans[tt++] = t;
for(int i=tt-1;i>=2;i--){
printf("%lld",ans[i]);
if(i != 2) printf(" ");
}
puts("");
}
int main(){
solve();
return 0;
}