【算法】【大数加法】

8 阅读1分钟

E. Final Countdown(1500)

#include<bits/stdc++.h>
using namespace std;
#define int long long 
signed main(){
	int t=1;cin>>t;
	while(t--){
	
	int n;cin>>n;
	string s;cin>>s;
	reverse(s.begin(),s.end());
	//个位,大位 
	vector<int>a(n+1);
	for(int i=n-1;i>=0;i--){
		a[i]=a[i+1]+(s[i]-'0');//个位是好多数的个位,累加 
		
	}string res;
	int c=0;
	for(int i=0;i<n;i++){
		c+=a[i];//先加最高位 
		res+=(char)(c%10+'0');//个位当前位 
		c/=10;//进位 
	}
	//882
	//88
	//8
	//个位出现1次
	//十位两次(十的二次方+十的一次方),百位3次( 十的三次方+十的二次方+十的一次方 
	//我们直接算 x/1 + x/10 + x/100… 会超级大,存不下。
	//d0 只出现在:x/1
    //d1 出现在:x/1、x/10
    //d2 出现在:x/1、x/10、x/100
	res+=(char)(c+'0');
	while(res.back()=='0'){
		res.pop_back();
	}reverse(res.begin(),res.end());
	cout<<res<<'\n';
}
	return 0;
}

解析

1.见注释

2.按位

如果从右往左给指示器编号(从 0 开始),那么第 i 位指示器恰好会翻转 ⌊s/10i⌋ 次。

为了计算这个和,我们把数字 s 拆成单独的数位,再累加每一位的贡献。

对 42:

  • 个位(i=0):42 / 1 = 42 次
  • 十位(i=1):42 / 10 = 4 次

总和:42 + 4 = 46