蓝桥杯 历届试题 数字游戏

26 篇文章 0 订阅
6 篇文章 0 订阅

题目链接:http://www.dotcpp.com/oj/problem1443.html(最近蓝桥一直举办校内赛可能服务器压力大卡的不行,而且这个网站没登陆也能查看题面比较方便一点)

在这里插入图片描述

先看到数据规模,如果纯暴力的话10^6 * 10^6肯定是要超时的,所以我们要想办法优化,因为我们只关心栋栋报出的数字总和,我们又知道了其他人报的规律是前面一个人的+1 +2 +3 +4这样报的,那么换句话来说,我们只要知道每循环一组总共加了多少,把这些总和加起来加到栋栋上次报的数字上,就能知道栋栋这次报的数字就多少了,再换句话说就是只需要等差数列求和就得出来了。
.
不考虑k的情况,假设有3个人报数
.
假定要知道第二个报的情况,只需要把这一轮的等差数列求和加到上次报的数字上就好了

然后忘记了等差数列的求和公式是什么,就开始推,然后就想了一下比较经典的1+2+3+…+100那个,大概就推到首尾项相加乘个数除以二,得出 n ( a n + a 1 ) / 2 n(a_n+a_1)/2 n(an+a1)/2,最后考虑k的情况,因为每次要报到k的时候从0开始报,实质上就是对k取余,这也是写这篇博客的原因,因为大家都知道(a*b)%k=(a%k+b%k)%k,然后套上去的时候我一不小心对 a n 和 a 1 a_n和a_1 ana1也取余了,结果疯狂WA,而且还能过部分数据不是全WA,当时还以为是我的求和公式推错了,上网搜了一下发现也没用我这种式子的(再次吐槽一下,好多人真的是复制粘贴代码就发博客啊),那时候刚好在和一个朋友聊天,然后朋友也说这个式子是可行的
在这里插入图片描述
最后就发现了是我手贱多打了两个取余,当然,至于 ( n ( a 1 % k + a n % k ) / 2 ) % k ! = S n % k (n(a_1\%k+a_n\%k)/2)\%k!=S_n\%k (n(a1%k+an%k)/2)%k!=Sn%k这里也是能通过数学证明的,这里就不详细展开了。
最后发一下AC代码,这里写的稍微“啰嗦了点”,本来很多能省略的,例如 a n a_n an是能通过 a 1 a_1 a1推出来的,不过我觉得这样写也增加了可读性,更符合数学公式

#include<iostream>
using namespace std;
long long ans=1,next_num=1,total,an,a1;
int main()
{
	int n,k,t;
	cin>>n>>k>>t;
	ans=1;
	an=n;
	a1=1;
	for(int i=1;i<t;i++)
	{
		next_num=(next_num+(n*(an+a1)/2)%k)%k;
		ans+=next_num;
		a1=an+1;
		an=an+n;
	}
	cout<<ans;
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值