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;	
} 

### C语言实现x进制减法 在C语言中,可以通过多种方法来实现不同进制下的减法操作。通常情况下,程序会先将输入的数从指定进制转换为十进制进行计算,然后再将结果转换回目标进制输出。 以下是基于上述原理的一个通用示例代码: ```c #include <stdio.h> #include <string.h> #include <ctype.h> // 将字符串形式的数值按给定基数(base)转换为整型 int convertToDecimal(const char *numStr, int base) { int result = 0; int length = strlen(numStr); for (int i = 0; i < length; ++i) { int digitValue = isdigit(numStr[i]) ? numStr[i] - '0' : toupper(numStr[i]) - 'A' + 10; if (digitValue >= base || digitValue < 0) { printf("Invalid number format or out of range.\n"); return -1; } result = result * base + digitValue; } return result; } // 将十进制数转换为目标进制表示的字符串 void convertFromDecimal(int num, int base, char *resultBuffer) { const char digits[] = "0123456789ABCDEF"; int index = 0; do { resultBuffer[index++] = digits[num % base]; num /= base; } while (num > 0); resultBuffer[index] = '\0'; strrev(resultBuffer); // 反转字符串以得到正确顺序 } // 主函数演示 x 进制减法 int main() { char num1[50], num2[50]; int base, decNum1, decNum2, diffDec; char result[50]; printf("Enter the base (between 2 and 16): "); scanf("%d", &base); if (base < 2 || base > 16) { printf("Base must be between 2 and 16.\n"); return 1; } printf("Enter first number in base-%d: ", base); scanf("%s", num1); printf("Enter second number in base-%d: ", base); scanf("%s", num2); decNum1 = convertToDecimal(num1, base); decNum2 = convertToDecimal(num2, base); if (decNum1 == -1 || decNum2 == -1) { return 1; } diffDec = decNum1 - decNum2; if (diffDec < 0) { printf("Result cannot represent negative numbers directly in this example.\n"); return 1; } convertFromDecimal(diffDec, base, result); printf("Difference in base-%d: %s\n", base, result); return 0; } ``` #### 关键点解析 - **进制转换**:通过`convertToDecimal`函数完成任意进制到十进制的转换[^1]。 - **逆向转换**:利用`convertFromDecimal`函数把差值重新映射至原始进制下表示[^2]。 - **边界条件处理**:需注意负数情况以及非法字符检测等问题[^3]。 此方案适用于任何介于二至十六之间的合法正整数范围内的基础运算需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值