【1041】 Computer Transformation 【递推 / 高精加法】

博客分享了作者在杭电在线评测系统(HDUOJ)刷题的经历,重点讨论了一道递推变化的题目。作者提到由于英语水平限制,起初使用翻译软件理解题意,但效果不佳,最终通过逐字翻译理解了题目。文章提供了两种解题方法,一种是直接模拟,但时间复杂度过高,另一种则是通过观察规律,采用高精度计算。博主给出了高精度加法模板,并展示了如何提前计算结果以避免重复计算导致超时。文章适合对算法和ACM竞赛感兴趣的读者。

在这里插入图片描述
http://acm.hdu.edu.cn/showproblem.php?pid=1041
唠嗑,吐槽
不得不说杭电里面的题真的新颖,我在其它oj上刷了不少题,最近才开始刷HDUoj,
以前觉得这个oj是英文的不爽,因为我的英语垃圾到了极致。
为了准备ACM省赛,只能硬着头皮刷杭电里的题,一来提升思维,而来能看懂英文题。
这道题题意没看懂,于是用了翻译软件翻译,结果翻译软件太坑了,弄的我不知道题目啥意思。
后来还是看英文一个个翻译才知道题意。

题意: 就是递推的变化,最后看一下有多少个 “00" 。

首先我们分析一下这该如何求?

第一种方法纯模拟: 按照题目的要求模拟。你会发现这样时间复杂度太高了 O(2n) 绝对的TLE 加 MLE。

第二种方法用算法来算: 你会发现这也没有考察啥算法。

于是,结果就是打表找规律。

模拟的代码:

#include<cstdio>
#include<iostream>
using namespace std;
int main(void) 
{
	int n;
	while(cin>>n)
	{
		string s="1";
		string ans;
		while(n--)
		{
			for(int i=0;i<s.size();i++)
			{
				if(s[i]=='0') ans+="10";
				else ans+="01";
			}
			s=ans;
			ans.clear();
		}
		cout<<s<<endl;
	}
	return 0;
}

在这里插入图片描述
规律十分的明显: s[ i ]= s[ i -1 ] + 2 x s [ i - 2 ]
分析后发现我们要用高精来算

注意要先将结果算出来,再输入n。
避免每输入一个n 计算一次,这样重复做了好几遍,会 TLE。

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;

vector<int> mul(vector<int> &A,int d)
{
	vector<int> C; int t=0;
	for(int i=0;i<A.size()||t;i++)
	{
		if(i<A.size()) t+=A[i]*d;
		C.push_back(t%10);
		t/=10;
	}
	while(C.size()>1&&C.back()==0) C.pop_back();
	return C;
}
vector<int> add(vector<int> &A, vector<int> &B)
{
	vector<int> C; int  t=0;
	for(int i=0;i<A.size()||i<B.size();i++)
	{
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t) C.push_back(1);
	return C;
}
int main(void)
{
	int n;
	vector<int>A[1005];
	A[0].push_back(0);
	A[1].push_back(0);
	A[2].push_back(1); 
	for(int i=3;i<=1001;i++)
	{
		A[i]=mul(A[i-2],2);
		A[i]=add(A[i],A[i-1]);
	} 
	while(cin>>n)
	{
		
		for(int i=A[n].size()-1;i>=0;i--) cout<<A[n][i];
		cout<<endl;
	}
	return 0;
}

其实写一个加法的模板就行了。

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(vector<int> &A, vector<int> &B)
{
	vector<int> C; int  t=0;
	for(int i=0;i<A.size()||i<B.size();i++)
	{
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t) C.push_back(1);
	return C;
}
int main(void)
{
	int n;
	vector<int>A[1005];
	A[0].push_back(0);
	A[1].push_back(0);
	A[2].push_back(1); 
	for(int i=3;i<=1001;i++)
	{
		A[i]=add(A[i-2],A[i-2]);
		A[i]=add(A[i],A[i-1]);
	} 
	while(cin>>n)
	{
		
		for(int i=A[n].size()-1;i>=0;i--) cout<<A[n][i];
		cout<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值