蓝桥杯2024年第十五届省赛真题-R 格式(高精度乘法 + 加法)

本文介绍了一种C语言实现的高精度乘法和加法模板,用于处理double类型与2的幂相乘并进行四舍五入的问题,包括高精度乘法函数`mul`和高精度加法函数`ADD`的详细实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题链接:蓝桥杯2024年第十五届省赛真题-R 格式 - C语言网

题目:

样例:

输入
2 3.14
输出
13

思路:

        根据题意,结合数据范围,这是一道模板的高精度乘以低精度问题。

        题意是double 类型 d 与 2 的n 次幂相乘,最后四舍五入。

        我们换一下视角,看作 对于double 类型 d ,与 n 个 2 相乘,最后四舍五入。

        这样就很快解出答案了,就是对于double小数部分需要微调一下即可。

高精度乘法模板函数如下:

        

// 高精度乘以低精度 模板
inline string mul(string A,int x)
{
	vector<int>a;	// 取出每一位
	int len = A.size();	// 倒着取每一位,方便低位到高位的计算
	
	for(int i = len - 1;~i;--i) a.emplace_back(A[i] - '0');
	
	vector<int>tem;	// 存储计算结果
	int t = 0;	// 存储临时进位数
	for(int i = 0;i < len;++i)
	{
		int num = t + a[i] * x;	// 开始每一位相乘
		tem.emplace_back(num % 10);	// 取计算结果个位
		t = num / 10;	// 计算进位
	}
	
	while(t > 0)
	{
		// 如果最后有高位的进位,我们进位
		tem.emplace_back(t % 10);
		t /= 10;
	}	
	
	string ans = "";	// 存储最后计算结果
	// 将结果转回为 string ,并返回结果
	int temlen = tem.size();
	for(int i = temlen - 1;~i;--i)	ans += char(tem[i] + '0');
	return ans;
}

  高精度加法模板函数如下:

// 高精度加法模板
inline string ADD(string A,string B)
{
	vector<int>a,b;
	int alen = A.size();
	int blen = B.size();// 倒着取每一位,方便低位到高位的计算
	for(int i = alen - 1;~i;--i) a.emplace_back(A[i] - '0');
	for(int i = blen - 1;~i;--i) b.emplace_back(B[i] - '0');
	
	vector<int>tem;	// 存储计算结果
	int t = 0;	// 存储临时进位数
	for(int i = 0;i < alen or i < blen;++i)
	{
		int num = t;	// 开始每一位相加
		if(i < alen) num += a[i];
		if(i < blen) num += b[i];
		tem.emplace_back(num % 10);// 取计算结果个位
		t = num / 10;// 计算进位
	}
	
	while(t > 0)
	{
		// 如果最后有高位的进位,我们进位
		tem.emplace_back(t % 10);
		t /= 10;
	}	
	
	string ans = "";	// 存储最后计算结果
	
	// 将结果转回为 string ,并返回结果
	int temlen = tem.size();
	for(int i = temlen - 1;~i;--i)	ans += char(tem[i] + '0');
	return ans;
}

代码详解如下:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define int long long
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;
inline void solve();

signed main()
{
//	freopen("a.txt", "r", stdin);
//	IOS;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}
	return 0;
}

// 高精度乘以低精度 模板
inline string mul(string A,int x)
{
	vector<int>a;	// 取出每一位
	int len = A.size();	// 倒着取每一位,方便低位到高位的计算
	
	for(int i = len - 1;~i;--i) a.emplace_back(A[i] - '0');
	
	vector<int>tem;	// 存储计算结果
	int t = 0;	// 存储临时进位数
	for(int i = 0;i < len;++i)
	{
		int num = t + a[i] * x;	// 开始每一位相乘
		tem.emplace_back(num % 10);	// 取计算结果个位
		t = num / 10;	// 计算进位
	}
	
	while(t > 0)
	{
		// 如果最后有高位的进位,我们进位
		tem.emplace_back(t % 10);
		t /= 10;
	}	
	
	string ans = "";	// 存储最后计算结果
	// 将结果转回为 string ,并返回结果
	int temlen = tem.size();
	for(int i = temlen - 1;~i;--i)	ans += char(tem[i] + '0');
	return ans;
}

// 高精度加法模板
inline string ADD(string A,string B)
{
	vector<int>a,b;
	int alen = A.size();
	int blen = B.size();// 倒着取每一位,方便低位到高位的计算
	for(int i = alen - 1;~i;--i) a.emplace_back(A[i] - '0');
	for(int i = blen - 1;~i;--i) b.emplace_back(B[i] - '0');
	
	vector<int>tem;	// 存储计算结果
	int t = 0;	// 存储临时进位数
	for(int i = 0;i < alen or i < blen;++i)
	{
		int num = t;	// 开始每一位相加
		if(i < alen) num += a[i];
		if(i < blen) num += b[i];
		tem.emplace_back(num % 10);// 取计算结果个位
		t = num / 10;// 计算进位
	}
	
	while(t > 0)
	{
		// 如果最后有高位的进位,我们进位
		tem.emplace_back(t % 10);
		t /= 10;
	}	
	
	string ans = "";	// 存储最后计算结果
	
	// 将结果转回为 string ,并返回结果
	int temlen = tem.size();
	for(int i = temlen - 1;~i;--i)	ans += char(tem[i] + '0');
	return ans;
}

inline void solve()
{
	
	int n;
	string d;
	bool vis = false;	// 检查是否符合四舍五入
	cin >> n >> d;
	
	// 如果 d 是整数的情况
	if((int)d.find(".") == -1)
	{
		while(n--)
		{
			d = mul(d,2);
		}
	}else
	{
		int pos = d.find(".");	// 找到 小数点 . 的位置下标
		
		int len = d.size() - pos - 1;	// 计算小数部分长度
		d.erase(d.begin() + pos);	// 删掉 小数点 .

		// 将 d 所有的数字当作整数相乘计算
		while(n--)
		{
			d = mul(d,2);
		}
		
		pos = d.size() - len;	// 更新小数点位置
		
		// 查看小数点后一位是否符合四舍五入
		if((d[pos] - '0') >= 5) vis = true;
		
		// 删掉小数部分,保留整数
		while(len--) d.erase(d.begin() + d.size() - 1);
		
		if(vis) d = ADD(d,"1");	// 如果符合四舍五入,那么进一
	}
	cout << d << endl;	
}

最后提交:

### 蓝桥杯 2024 第十五届 R格式 题目解析 以下是关于蓝桥杯 2024 第十五届涉及的几类典型问题及其解析,重点围绕 **R语言** 的实现方式展开。 --- #### 一、因数计数问题 (Factor Counting) 该问题是通过寻找满足特定条件的有序四元组来解决。原始方法可能采用暴力枚举的方式,但由于时间复杂度过高,在实际应用中不可取。优化后的算法可以利用集合去重以及高效的数据结构降低运行成本[^2]。 ##### 实现逻辑 1. 枚举所有可能的二元组 `(i, j)`,其中 `j` 是 `i` 的倍数。 2. 将这些符合条件的二元组存入集合以去除重复项。 3. 基于上述集合中的数据生成最终的四元组 `(i, j, k, l)`,并统计总数。 ##### R代码示例 ```r factor_count <- function(nums) { pairs_set <- set() # 寻找所有有效的(i,j)组合 n <- length(nums) for (i in seq_len(n)) { for (j in seq_len(n)) { if (nums[j] %% nums[i] == 0 && i != j) { # 判断是否为因子关系 pairs_set[[paste(i, j)] <<- TRUE # 存储唯一键值对 } } } quadruples_count <- 0 # 组合生成四元组 pair_keys <- names(pairs_set) m <- length(pair_keys) for (k in seq_len(m)) { for (l in seq_len(m)) { key_k <- strsplit(pair_keys[k], split=" ")[[1]] key_l <- strsplit(pair_keys[l], split=" ")[[1]] if (!(key_k[1] %in% c(key_l[1], key_l[2]) || key_k[2] %in% c(key_l[1], key_l[2]))) { quadruples_count <- quadruples_count + 1 } } } return(quadruples_count) } ``` --- #### 二、团建游戏问题 (Team Building Game) 此问题的核心在于找到两棵不同树之间的最长公共前缀路径长度。具体来说,给定两个树形结构,每条从根节点到叶子节点的路径都可以看作是一个正整数序列。目标是比较这两个序列的最大匹配部分[^3]。 ##### 思路分析 - 使用深度优先搜索(DFS),记录下每棵树的所有路径; - 对两条路径列表逐一比较其共同起始片段; - 输出最大匹配长度作为得分。 ##### R代码示例 ```r dfs_tree_paths <- function(tree, node=1L, path=c()) { current_path <- append(path, tree$nodes[node]) if (!is.null(tree$children[[node]])) { paths_list <- list() for(child_node in tree$children[[node]]) { child_result <- dfs_tree_paths(tree, child_node, current_path) paths_list <- c(paths_list, child_result) } return(unlist(paths_list)) } else { return(list(current_path)) } } longest_common_prefix_length <- function(seq_a, seq_b){ min_len <- min(length(seq_a), length(seq_b)) prefix_length <- 0 while(prefix_length < min_len && seq_a[prefix_length+1]==seq_b[prefix_length+1]){ prefix_length <- prefix_length + 1 } return(prefix_length) } calculate_max_score <- function(tree_1, tree_2){ all_paths_t1 <- unlist(dfs_tree_paths(tree_1)) all_paths_t2 <- unlist(dfs_tree_paths(tree_2)) max_score <- 0 for(path_i in all_paths_t1){ for(path_j in all_paths_t2){ common_len <- longest_common_prefix_length(path_i, path_j) if(common_len > max_score){max_score <- common_len} } } return(max_score) } ``` --- #### § 相关问题 § 1. 如何进一步优化基于集合操作的时间效率? 2. 如果输入规模增大至百万级别,现有解决方案是否存在瓶颈?如何改进? 3. 是否存在其他更高效的动态规划或者分治策略适用于此类问题? 4. 在处理大规模图论问题时,除了 DFS 外还有哪些常用遍历技术适合用在 R 中? 5. 当面对多维约束条件下(如权重限制),应采取何种扩展模型设计新的评分机制?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值