3、数列求和(加强版是什么鬼)

  今天看书才发现return 0有多么重要,之前一直认为可有可无,基本没写,之后一定会改正这个烂习惯。

题目

  给定某数字A(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+A**A+AAA+⋯+A**AANA)。例如A=1, N=3时,S=1+11+111=123。

分析

  这时铁有人跳出来,这么简单的题都好意思发出来,这不直接用循环就能搞定的问题,散了散了。

  阿哲

  我一开始也是这么想的,几次想跳过这道题,但想来想去放在算法书里一定有它的道理。于是我用最基础的方法做了一次。
基础代码

#include<stdio.h>
int main()
{
	int A, time, K, S, i;
	scanf("%d %d", &A, &time);
	S = K = A;
    if (time == 0)
	{
		printf("0");
		return 0;
	}
	for (i = 1; i < time; i++)
	{
		K = K * 10 + A;
		S += K;
	}
	printf("%d", S);
	return 0;
} 

果然不出所料,出问题了。
在这里插入图片描述
  题目给的时int变量,但如果time = 100,输出就会超过int的最大范围231-1了,因此测试没有通过。

  题目并没有要求输出整型,那我们完全可以使用数组以循环的方式把每一位都分开输出,最后组合成结果。

  所使用的方法就是按位相加。举个例子,输入1 3,进行1 + 11 + 111,做了3次加法,需要三次循环。

第一次循环:个位 +1

第二次循环:十位 + 1,个位 +1

第三次循环: 百位 + 1,十位 + 1,个位 +1

最终把这三个位置上的数字输出,得出结果。

  代码命名解释:S[N] :存放每一位上的数字。K[N]:存放一个数组,每一项都是A。C:表示进位,如果个位上的数的和超过10,则十位的数字就 + 1。

方法一代码

#include<stdio.h>
#define N 100000
int main()
{
	int S[N], K[N], C = 0;
	int A, time;
	int i, j;
	scanf("%d %d", &A, &time);
	if (time == 0)
	{
		printf("0");
		return 0;
	}
	for (i = 0; i < time; i++)
	{
		S[i] = 0;//数和的每一位为0
		K[i] = A;//列表的每一位都为A
	}
	for (i = 0; i < time; i++)//位运算
	{
		for (j = 0; j <= i; j++)
		{
			S[j] += K[j] + C;
			C = S[j] / 10;//超过10的部分,进位
			S[j] %= 10;//位上的数字必须小于10
		}
	}
	if (C != 0)//如果最高位大于10,则需要在向前进一位
		printf("%d", C);
	for (i = time - 1; i >= 0; i--)//逆序输出每一位的结果
		printf("%d", S[i]);
	printf("\n");
	return 0;
} 

  然后,问题又来了。
在这里插入图片描述
  因为使用了嵌套循环,时间复杂度成了N2,导致在规定的时间内没有完成100000次运算,因此,还得改进这个算法。

  不妨这么想,个位相当于做了time次的A值相加,十位相当于做了time - 1次的A值相加,那就可以用乘法来代替相加,超出的10部分依然进位解决。
方法二代码

#include<stdio.h>
#define N 100000
int main()
{
	int S[N], K[N], C = 0;
	int A, time;
	int i, j;
	scanf("%d %d", &A, &time);
	if (time == 0)
	{
		printf("0");
		return 0;
	}
	for (i = 0; i < time; i++)
	{
		S[i] = 0;//数和的每一位为0
	}
	for (i = 0; i < time; i++)
	{
		S[i] = A * (time - i) + C;
		C = S[i] / 10;
		S[i] %= 10;
	}
	if (C != 0)
		printf("%d", C);
	for (i = time - 1; i >= 0; i--)
		printf("%d", S[i]);
	printf("\n");
	return 0;
} 

在这里插入图片描述
  还就那个折磨人。永远不要小看每一道题,它总会在你认为正确的地方给你来两个坑。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值