Addition(9.25ICPC第二场M)

题目描述

在这里插入图片描述

输入描述

在这里插入图片描述

输出描述

在这里插入图片描述

输入样例

32
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

输出样例

0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

提示

在这里插入图片描述
特别注意:输出的 Vci 只能为 0 / 1 。


题目大意: 给定符号位数组 sgn [ ] ,及数组 Va [ ] , Vb [ ] 表示数值 a 和 b 的各个数位,现规定数值 a ,b 的计算方式为题中公式,需求 a + b 后所得的答案 c 通过该公式转化后表示各个数位的 Vc [ ] 数组。

不难发现本题公式中 2 的 i 次方正好反应了二进制对应每一位的权值,得到的结果为:高位在右侧,低位在左侧。即对于序列 1110 ,对应后 a 的值为 0111 ,而 sgn [ ] 为控制每一位的符号。

在这里插入图片描述

因此本题的计算方式即可转化为(仅考虑符号位都为 + 1 时):对数组 Va 和 Vb 由低位向高位进行该位的相加及进位,处理后得到的每一位的答案即为 Vc 的对应位,由此样例可得:1 + 111 = 1000(该运算过程中前导 0 均省略),将 1000 倒序输出后即可。

当符号位存在 - 1 时,为了方便辨别 Vc 中对应位的正负,可在 Vc [ ] 数组中添加负号加以区分,例(此处规定的数组下标是为了更好演示示例):① sgn [ i ] = - 1,Va [ i ] = 1,Vb [ i ] = 0 时,Vc [ i ] = - 1;② sgn [ i ] = - 1,Va [ i ] = 1,Vb [ i ] = 1 时,Vc [ i ] = 0 ,Vc [ i + 1] 由于进位 = - 1 ;

然而,由于输出的 Vc 只能为 0 / 1,因此需要对存在 - 1 可能性的原 Vc 数组进行变换,以下通过三种情况进行分类讨论。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其中,例 1 与 2 、3 的区别为:对于处理完进位但仍存在符号的数组 c ,是否存在与数组 sgn 符号相反(即其中一个为 - 1,另一为 + 1)的情况,而当出现该情况时,需要进行特殊处理,否则直接取该位的绝对值即可。

例 2 中,由于位权 2 的进位使位权 4 中出现了数组 c 与符号位 sgn 相反的情况。本样例中,由于 a、b 都含有位权 2 ,因此对 c 的贡献应为 ( + 2 )+ ( + 2 ),进位后应取 ( + 4 ),但由于位权 4 的符号位 sgn 为 - 1 ,因此此处对 c 的贡献为( - 4 )。而由于符号位 sgn 的值已经确定,因此只能通过配凑的方式使得对 c 的贡献仍然为( + 4 ),即令后一位( 位权 8 )进行 加一 处理, 得到( + 8 )+( - 4 )=( + 4 );

同理,在例 3 中,由于位权 8 处的符号相反,因此需要令( - 16 ) +( + 8 )=( - 8 )进行配凑,即令后一位进行 减一 处理。而由于连锁反应,位权 16 又会将 - 2 进行进位,直到该操作对后续位再无影响为止。

因此本题的核心为判断数组 c [ ] 与数组 sgn [ ] 是否相反,当 sgn = 1 且 c = - 1 时,对后一位进行 - 1 处理;当 sgn = - 1 且 c = 1 时,对后续位进行 + 1 处理,并不断对后续进行遍历保证其合法性。

参考代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100;
int a[N],b[N],s[N],ans[N],c[N];

int main(){
    
    
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int n;cin>>n;
	for(int i=0;i<n;i++)cin>>s[i];
	for(int i=0;i<n;i++)cin>>a[i];
	for(int i=0;i<n;i++)cin>>b[i];
	for(int i=0;i<n;i++){
    
    
		c[i]+=s[i]*a[i]+s[i]*b[i];
		if(c[i]>=2){
    
    
			c[i]=c[i]%2;
			c[i+1]++;
		}
		if(c[i]<=-2){
    
    
			c[i]=c[i]+2;
			c[i+1]--;
		}
	}
	for(int i=0;i<n;i++){
    
    
		if(s[i]==-1&&c[i]==-1)ans[i]=1;
		if(s[i]==1&&c[i]==1)ans[i]=1;
		if(c[i]==0)ans[i]=0;
		if(s[i]==-1&&c[i]==1){
    
    
			ans[i]=1;
			c[i+1]++;
			for(int j=1;j+i<n;j++){
    
    
				if(c[i+j]==2){
    
    
					c[i+j]=0;
					c[i+j+1]++;
				}else break;
			}
		}
		
		if(s[i]==1&&c[i]==-1){
    
    
			ans[i]=1;
			c[i+1]--;
			for(int j=1;j+i<n;j++){
    
    
				if(c[i+j]==-2){
    
    
					c[i+j]=0;
					c[i+j+1]--;
				}else break;
			}
			
		}
	}

	for(int i=0;i<n;i++){
    
    
		cout<<ans[i];
		if(i!=n-1)
			cout<<' ';
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/laysan/article/details/120479661