HDU1041-Computer Transformation(递推+大数)

A sequence consisting of one digit, the number 1 is initially written into a computer. At each successive time step, the computer simultaneously tranforms each digit 0 into the sequence 1 0 and each digit 1 into the sequence 0 1. So, after the first time step, the sequence 0 1 is obtained; after the second, the sequence 1 0 0 1, after the third, the sequence 0 1 1 0 1 0 0 1 and so on.

How many pairs of consequitive zeroes will appear in the sequence after n steps?
Input
Every input line contains one natural number n (0 < n ≤1000).
Output
For each input n print the number of consecutive zeroes pairs that will appear in the sequence after n steps.
Sample Input
2
3
Sample Output
1
1

分析:

题意:
如果根节点是1 则左右子节点分别是0、1,如果根节点是0则左右子节点分别是1、0,现在给出根节点是一个数字1,问,第n次变换产生多少对00?
在这里插入图片描述
解析:
经过分析发现,数字1经过两次变换后会出现一对00,然后就是一对00经过两次变换后出现一对00,那么我们用sum[N]数组记录这一次变换有多少个1产生,dp[N]数组记录这次变换有多少对00产生!

于是我们写出状态转移方程为:
dp[i]=dp[i-2]+sum[i-2];

但是,你发现没有?输入n的最大取值是1000,sum[1000]=sum[999]*2;
dp[1000]=dp[998]+sum[998];经过一次变化有1个1,二次变化有2个1,三次就是4个1,数字1的数量是按指数级增长的,指数达到30就不得了了,更何况1000呢?
所以这里还要大数算法!

代码写出来之后,我们发现sum[i-2]+dp[i-2]==dp[i-1]+2*dp[i-2];这样我们就可以再减少sum[N]数组部分数据的处理!

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 1005

using namespace std;

int dp[N][N];

int main()
{
	int n;
	dp[0][0]=dp[1][0]=dp[2][0]=dp[2][1]=1;
	dp[0][1]=dp[1][1]=0;
	for(int i=3;i<=1000;i++)
	{
		int temp=max(dp[i-1][0],dp[i-2][0]),v=0;
		for(int j=1;j<=temp;j++)
		{
			dp[i][j]=2*dp[i-2][j]+dp[i-1][j]+v;
			v=dp[i][j]/10;
			dp[i][j]%=10;
		}
		dp[i][0]=temp;
		while(v!=0)
		{
			dp[i][0]++;
			dp[i][temp+1]=v%10;
			v/=10;
		}
	}
	while(~scanf("%d",&n))
	{
		for(int i=dp[n][0];i>0;i--)
		{
			printf("%d",dp[n][i]);
		}
		printf("\n");
	}
	return 0;
 }
发布了46 篇原创文章 · 获赞 16 · 访问量 383

猜你喜欢

转载自blog.csdn.net/weixin_43357583/article/details/105207567
今日推荐