X 进制减法

一、题目描述

P8782 [蓝桥杯 2022 省 B] X 进制减法

二、算法简析

首先,要弄清楚如何转换为十进制。先来看二进制数 a n a n − 1 . . . a 0 a_na_{n-1}...a_0 anan1...a0,转换为十进制为 a n 2 n + a n − 1 2 n − 1 + ⋅ ⋅ ⋅ + a 0 2 0 a_n2^{n}+a_{n-1}2^{n-1}+···+a_02^0 an2n+an12n1+⋅⋅⋅+a020
当不同位的进制不同时,公式是不同的。令 a i a_i ai n i n_i ni 进制,则 a i a i − 1 . . . a 0 a_ia_{i-1}...a_0 aiai1...a0 中的 a i a_i ai 转换为十进制为 a i ∏ 0 i − 1 n i a_i\prod_0^{i-1}n_i ai0i1ni,以此类推求出 a i − 1 . . . a 0 a_{i-1}...a_0 ai1...a0,再相加。
321 为例,最低位为二进制,第二位为十进制,第三位为八进制。该数转换为十进制为 3 × 20 + 2 × 2 + 1 = 65 3\times 20+2 \times 2 + 1 = 65 3×20+2×2+1=65
接着,再来看本题,要我们求 A − B A-B AB 的最小值。我们采用贪心,使 A A A B B B 转换为十进制的值最小,也就是说使每位的进制尽量小。每一位的进制为:

{ max ( A [ i ] , B [ i ] ) + 1 , A [ i ] ,   B [ i ] ≥ 2 2 , A [ i ] ,   B [ i ] < 2 \begin{cases} \text{max}(A[i], B[i]) + 1&, A[i],~B[i]\geq 2 \\ 2&,A[i],~B[i]<2 \end{cases} {max(A[i],B[i])+12,A[i], B[i]2,A[i], B[i]<2

值得注意的是, A A A B B B 的位数可能不相同,但都必须是低位对齐。

三、本体代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int MAX = 1e5 + 5;
const int MOD = 1e9 + 7;

int N, Ma, Mb, A[MAX], B[MAX], C[MAX];
int a, b;

int quickin(void)
{
	int ret = 0;
	bool flag = false;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-')    flag = true;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9' && ch != EOF)
	{
		ret = ret * 10 + ch - '0';
		ch = getchar();
	}
	if (flag)    ret = -ret;
	return ret;
}

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	N = quickin();
	// A和B的位数可能不同,但都是低位对齐 
	Ma = quickin();
	for (int i = Ma - 1; i >= 0; i--)
		A[i] = quickin();
	Mb = quickin();
	for (int i = Mb - 1; i >= 0; i--)
		B[i] = quickin();
	
	int cj = 1;
	for (int i = 0; i < Ma || i < Mb; i++)
	{
		int tmp = 0;
		if (i < Ma)
			tmp = max(tmp, A[i]);
		if (i < Mb)
			tmp = max(tmp, B[i]);
		
		tmp = tmp < 2 ? 2 : tmp + 1;
		C[i] = cj;
		cj = (ll)cj * tmp % MOD;
	}
	
	for (int i = 0; i < Ma || i < Mb; i++)
	{
		if (i < Ma)
			a = ((ll)A[i] * C[i] % MOD + a) % MOD;
		if (i < Mb)
			b = ((ll)B[i] * C[i] % MOD + b) % MOD;
	}
	
	// (a - b + MOD) % MOD 保证余数不小于0 
	cout << ((ll)a - b + MOD) % MOD << endl;
	
	return 0;	
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值