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. 解题思路:
    首先:
    51-nod 1346_第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
#include
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]))<

你可能感兴趣的:(动态规划)