51-nod 1346

  1. Problem link:
    51-nod 1346 5级算法题

  2. Probelm Description:
    Problem Description:
    函数f(n,m)
    {
    若n=1或m=1返回a[n][m];
    返回f(n-1,m)异或f(n,m-1);
    }
    读入2<=n,m<=100
    for i=2->100读入a[1][i]
    for i=2->100读入a[i][1]
    输出f(n,m)
    发现当n,m较大时程序变得异常缓慢。
    小b经过一番思考,很快解决了这个问题。
    这时小c出现了,我将n,m都增加131072,你还能解决吗?
    相对的,我会读入2->131172的所有a[1][i]和a[i][1]。
    小b犯了难,所以来找你,你能帮帮他吗?

输入

第一行读入131171个正整数,表示i=2->131172的a【1】【i】(1<=a[1][i]<=1000000000)。
第二行读入131171个正整数,表示i=2->131172的a【i】【1】(1<=a[i][1]<=1000000000)。
第三行读入一个正整数Q(1<=Q<=10000),表示询问的次数。
接下来Q行,每行两个数n,m(2<=n,m<=100),表示每一组询问。

输出

Q行,每行为f(n+131072,m+131072)

输入样例

2 3 4 5 6 7 8 … 131171 131172
2 3 4 5 6 7 8 … 131171 131172
3
2 2
2 3
2 4

输出样例

0
0
131072

  1. 解题思路:
    首先:
    在这里插入图片描述
    递推易得:
    f[n][m]=f[n-2^x] [m] ^ f[n][m-2^x] (x=0,1,2,3…)此题目中须知:131072是2的18次方,则此题目只需要记忆化搜索一下求出f[100][131172]与f[131172][100]的两个数组的值即可。改天补一个用递推完成的代码,现在已经凌晨两点多了,我比较懒,不想补了。我看别人都是用递推写的,就我写了个记忆化搜索。

  2. AC code:

#include<iostream>
#include<cstring>
using namespace std;
const int N=131175;
int a[N],b[N],n,m,t,q,dp1[105][N],dp2[N][105];
int f1(int n,int m){
	if(dp1[n][m]!=-1)return dp1[n][m];
	if(n==1)return dp1[n][m]=a[m];
	else if(m==1)return dp1[n][m]=b[n];
	else return dp1[n][m]=f1(n-1,m)^f1(n,m-1);
}
int f2(int n,int m){
	if(dp2[n][m]!=-1)return dp2[n][m];
	if(n==1)return dp2[n][m]=a[m];
	else if(m==1)return dp2[n][m]=b[n];
	else return dp2[n][m]=f2(n-1,m)^f2(n,m-1);
}
int  main(){
	ios::sync_with_stdio(false);cin.tie(0);
	for(int i=2;i<=131172;i++)cin>>a[i];
	for(int i=2;i<=131172;i++)cin>>b[i];
	memset(dp1,-1,sizeof(dp1));
	memset(dp2,-1,sizeof(dp2));
	f1(100,131172);
	f2(131172,100);
	cin>>q;
	while(q--){
		cin>>n>>m;
		cout<<((dp1[n][m+131072])^(dp2[n+131072][m]))<<endl;
	}
}
### 关于51Nod平台上编号为1020的问题详情与解答 #### 问题描述 在51Nod平台上的第1020号问题是关于计算两个大整数相加的结果[^1]。给定两个正整数A和B,长度不超过10^6位,要求编写程序来求解这两个数的和。 #### 输入格式说明 输入数据由多组测试案例组成;每组测试案例占两行,分别表示要相加的大整数A和B。对于每一组测试案例,应当单独输出一行结果,即A+B的值。 #### 解决方案概述 解决此问题的关键在于处理超大数据类型的运算,在大多数编程语言中内置的数据类型无法直接支持如此大规模数值的操作。因此,可以采用字符串的方式来存储这些大整数,并实现逐位相加逻辑,同时考虑进位情况。 下面是一个Python版本的具体实现方法: ```python def add_large_numbers(a: str, b: str) -> str: # Reverse strings to make addition easier from least significant digit a = a[::-1] b = b[::-1] carry = 0 result = [] max_length = max(len(a), len(b)) for i in range(max_length): digit_a = int(a[i]) if i < len(a) else 0 digit_b = int(b[i]) if i < len(b) else 0 total = digit_a + digit_b + carry carry = total // 10 current_digit = total % 10 result.append(str(current_digit)) if carry != 0: result.append(str(carry)) return ''.join(reversed(result)) if __name__ == "__main__": while True: try: num1 = input().strip() num2 = input().strip() print(add_large_numbers(num1, num2)) except EOFError: break ``` 该代码片段定义了一个函数`add_large_numbers`用于接收两个作为参数传入的大整数(形式上为字符串),并返回它们之和同样作为一个字符串。通过反转输入字符串使得最低有效位位于索引位置0处从而简化了按位累加的过程。最后再将得到的结果列表反向拼接成最终答案输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值