吉首大学第十届“新星杯”大学生程序设计大赛 A题题解

这是一场很毒瘤的比赛。
鲁大师在一个星期前通知我们去打这场比赛,说名次高的有奖品,还说去年他们去参加这场比赛拿了前几名拿了个U盘…(疯狂暗示比赛很简单比赛很简单
单纯的我真的信了
赛后得知这场比赛是一场cf1800水平的比赛
心里一万个TMD
这次比赛前两个小时,凭借我单身18年的手速,AC了5道题,排名最高追到了20名,那时候我觉得这把有了,但没想到之后的三个小时疯狂吃T,一题都没过…比赛结束后感觉人被掏空了。
这次比赛的题我都会写题解,但因为我马上就要期末考试了,所以每天只会写一篇题解。
下面看A题:
在这里插入图片描述
一看此题,我第一反应是签到题,快速幂这东西肯定是被玩烂的板子,但看了几分钟后疯狂打脸,这尼玛是啥东西?
在比赛的时候我发现 n 的复杂度是有规律的,但问题求的是前 n 的和。所以就没想到可以通过打表找规律写。
学长经验一:暴力出奇迹,打表拿省一!
打表:
在这里插入图片描述
其实一开始我看不出有啥很清晰的规律。但把表给重新组合一下:

1
3 4
7 8 9 10
15 16 17 18 19 20 21 22
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

duang~duang
奇迹出现了!就是这么神奇!就是这么美妙!就是这么TMD
通过找规律,我们可以得出两个结论:
结论一:第i行的第一个数一定是 pow(2,i)-1。
结论二:第i行前(包括第 i 行元素)一共有 pow(2,i)-1。
所以如果要计算前 n 的和,可以利用等差数列的求和公式,然后再处理不满一行的数就可以了。

所以AC代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
	ios::sync_with_stdio(false);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,i;
		ll sum=0;
		scanf("%d",&n);
		if(n==0){cout<<0<<endl;continue;}
		for(i=1;pow(2,i)-1<n;i++)
		{
			sum+=(ll)pow(2,i-1)*((ll)pow(2,i+1)+(ll)pow(2,i-1)-3)/2;	
		}
		sum+=((ll)pow(2,i+1)-2+n-(ll)pow(2,i-1))*(n-(ll)pow(2,i-1)+1)/2; 
		printf("%lld\n",sum);
	} 
	return 0;
}

这里也要提出一个重要点:比赛的时候一定要把cin和cout换成scanf和printf。
我用这道题做了一个小测试。
即对比:

ios::sync_with_stdio(false);
cin>>n;

scanf("%d",&n);

他们的运行速度。一开始我认为开了ios::sync_with_stdio(false); cin流就可以和scanf一样快,但交了一发后发现会T。


通过这次比赛,我深刻的认识到一点,让我和诸佬之间有距离的不是手速,而是脑子。
所以我再这里给诸佬磕头了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值