洛谷 P1028 数的计算

AC代码(迭代):
和题解里那个激动的小伙子写的几乎一样……
这题目描述也有点迷,应该这样说:
1.不作任何处理;
2.在它的左边加上一个自然数,但该自然数不能超过首位数字的一半;
3.加上数后,继续按此规则进行处理,直到不能再加自然数为止.
由于每次首位至少会减半,所以最后总是会回到1。
比如1,不能加(没有比1的一半还小的正整数),只有自己,所以有一种。
2,左边可以加1,得到12,算作一种,还加上自己,有两种。
3,左边可以加1,得到13,还加上自己,有两种。
4,左边可以加1,2,得到14,24两种,其中24左边还可以加1,得到124,第三种,加上自己,共四种。
……
写几项后我们发现,我们只关心首位数字时什么,其实和后面没啥关系。
递推次数可以发现呢
f1->1
f2->1+f1=1+1=2
f3->1+f1=1+1=2
f4->1+f2+f1=4
f5->1+f2+f1=4
f6->1+f3+f2+f1=3+2+1=6

#include <stdio.h>
int main(int argc, char const *argv[])
{
	int i,j,n;scanf("%d",&n);
	int r[n+1];
	for(i=0;i<n+1;i++)
		r[i]=0;//用r[0]=0,从1开始迭代效果和用r[1]=1,从2开始迭代一样
		//索性就这么写了 
	for(i=1;i<=n;i++)
		{
			for(j=1;j<=i/2;j++)
				r[i]+=r[j];//所有不超过首位一半的函数值求和 
			r[i]++;//加上自己,不变也是满足的 
		}
	printf("%d",r[n]);
}

递归版本:
这个没法AC的,递归会大量计算重复的值,数字大了之后效率非常低。

#include <stdio.h>
int main(int argc, char const *argv[])
{
	int n;
	scanf("%d",n);
	printf("%d",count(n));
	return 0;
}

int count(int n)
{
	if(n==1) return 1;
	else
	{
		int sum=0,j;
		for(j=1;j<=n/2;j++)
			sum+=count(j);
		sum++;
		return sum;
	}
}

写的更鬼畜一点

#include <stdio.h>
int main(int argc, char const *argv[])
{
	int n;
	scanf("%d",n);
	printf("%d",count(n));
	return 0;
}

int count(int n)
{return (n==1)?1:sumTillOne(n);}

int sumTillOne(int n)
{return (n==1)?count(1):count(n)+sumTillOne(n-1);}

猜你喜欢

转载自blog.csdn.net/weixin_43873801/article/details/86607380
今日推荐