oj1344题求和:对于正整数n,k,我们定义这样一个函数f,它满足如下规律:······现在给出n和k,你的任务就是要计算f(n,k)的值。

oj1344题求和

原题:

在这里插入图片描述

分析即实现

这是一道数学题,我们很容易想到,只要找到了这个函数的解析式,这个问题便可以迎刃而解,加上计算机强大的计算能力,该题应当是可以很快完成计算的,然后可以观察这个式子,得到an的表达式:
在这里插入图片描述
然后逐项叠加,于是我们便有了以下解法:

#include <iostream>
#include <cmath>
using namespace std;

long long solve(long long n,long long k)
{
	long long num=0; 
	for (long long i=1;i<=n;i++)
		num+=pow(-1,(i-1)/k+1)*i;
	return num;
}
int main()
{
	int T;
	cin >> T;
	long long n;
	long long k;
	while(T--)
	{
		cin >> n >> k;
		cout << solve(n,k) << endl;
	}
	return 0;
}

可惜的是,oj报不通过,超时了,想想也是,pow()函数会花费不少的时间,于是我便思考如何消掉这个pow()函数,于是最终写出来以下代码:

#include <iostream>
using namespace std;

long long solve(long long n,long long k)
{
	long long num=0; 
	for(long long i=1;i<=n;i++)
	{
		if (((i-1)/k+1)%2!=0)
			num+=(-i);
		else
			num+=i;
	}
	return num;
}
int main()
{
	int T;
	cin >> T;
	long long n,k;
	while(T--)
	{
		cin >> n >> k;
		cout << solve(n,k) << endl;
	}
	return 0;
}

该方法的思想和第一种是一样的,但是消掉了pow函数,心想这次一定可以通过了,奈何再次爆出超时警告,噗,心累啊!怎么办?再想想,能不能换一种方法。
第三种方法:
可以将k看成一个小周期,2k看成一个大周期,那n/2k就表示大周期的个数,每个大周期的值很容易知道是k*k,那么我们很容易知道前面这个部分的值就是n/2k * k^2,再加上后面多出的部分就是结果,于是我又可以写出一个代码:

#include <iostream>
using namespace std;

long long solve(long long n,long long k)
{
	long long x=n/(2*k)*k*k;
	long long a=n%(2*k),b=n-a+1;
	if (n%(2*k)==0)
		return x;
	else if (a/(k+1)==0)
	{
		for (long long i=b;i<=n;i++)
			x+=(-i);
		return x;
	}
	else
	{
		for (long long i=b;i<b+k;i++)
			x+=(-i);
		for (long long i=b+k;i<=n;i++)
			x+=i;
		return x;
	}
}
int main()
{
	int T;
	cin >> T;
	long long n;
	long long k;
	while(T--)
	{
		cin >> n >> k;
		cout << solve(n,k) << endl;
	}
	return 0;
}

哈哈,终于通过了!
小提示:
在做这个题的时候,我最开始用int定义,最后发现越界,所以大家在写oj时千万要注意使用long long哦!
ps:
这三个代码经过测试,都是正确的,但是在oj上跑的话,1和2都超时了,只有3可以完美通过。
如果对你有帮助的话,不妨点个赞再走呗!

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值