【等差数列】题解

Link

给你一个长为 n n n,首项为 a a a,公差为 d d d 的等差数列。

x x x 中任选两个数 x i , x j x_i,x_j xi,xj ,同时满足:

  • x i + x j x_i+x_j xi+xj 为偶数。

  • x x x 中没有 x i + x j 2 \frac{x_i+x_j}{2} 2xi+xj

那么你就可以将 x i + x j 2 \frac{x_i+x_j}{2} 2xi+xj 加入 x x x 中,称为一次操作。

注意:新加入的数也可被选择。

问你最多能进行几次操作?


蒟蒻第一次打月赛,激动地点开第一题:

哇,好简单!

30min 后,终于 AC 了。(我好菜啊)


正文:

首先,这个数列是等差数列,也就是说,每两个相邻元素所构成的子区间 [ x i , x i + 1 ] [x_i,x_{i+1}] [xi,xi+1] 中,能产生的新数是一样的。那么,我们就只用算出每两个元素之间能产生多少个新数,再乘以子区间数 n − 1 n-1 n1 即可。

可能大家会有疑问,万一两个不同子区间中产生的新数又产生了新数呢?

其实原因很简单,因为这两个数所产生的新数,必定会由其中一个子区间中的数产生,那么这时候就重复计算了。所以直接把问题简化成计算两个相邻元素产生的新数即可。

我们来推导一下吧:

设有一集合 A A A,当前有两个元素 { A 1 , A 2 } \left \{ A_1,A_2 \right \} {A1,A2}

首先判断 A 1 + A 2 A_1+A_2 A1+A2 是否是偶数,若不是,则不能再产生数。

根据题目, A 1 A_1 A1 为首项,公差为 d d d

∴ A 2 = A 1 + d \therefore A_2 = A_1 + d A2=A1+d

∴ A 1 + A 2 = 2 A 1 + d \therefore A_1 + A_2 = 2A_1 + d A1+A2=2A1+d

∴ A 1 + A 2 2 = A 1 + d 2 \therefore \frac{A_1 + A_2}{2} = A_1 + \frac{d}{2} 2A1+A2=A1+2d

所以,判断 A 1 + A 2 A_1 + A_2 A1+A2 是否为偶数,就是 d d d 是否为偶数。这也就等于,如果 d d d 为奇数,就连一个数也产生不了,答案为 0 0 0

若设 d d d 为偶数,则第一次后的集合变成了 { A 1 , A 1 + A 2 2 , A 2 } \left \{ A_1,\frac{A_1+A_2}{2}, A_2 \right \} {A1,2A1+A2,A2}。这个数列也是一个等差数列,因为前后两个子区间产生的新数是一样的,所以直接判断左子区间 { A 1 , A 1 + A 2 2 } \left \{ A_1,\frac{A_1+A_2}{2} \right \} {A1,2A1+A2}。此时 d d d 又更新为 A 1 + A 2 2 − A 1 \frac{A_1+A_2}{2}-A_1 2A1+A2A1。继续判断 d d d 的奇偶,直到 d d d 为奇数才停止。

又容易发现:

∵ d 1 = A 1 + A 2 2 − A 1 \because d_1 = \frac{A_1+A_2}{2}-A_1 d1=2A1+A2A1

∴ d 1 = A 1 2 + A 2 2 − A 1 = A 2 2 − A 1 2 = A 2 − A 1 2 \therefore d_1 = \frac{A_1}{2}+\frac{A_2}{2}-A_1=\frac{A_2}{2}-\frac{A_1}{2}=\frac{A_2-A_1}{2} d1=2A1+2A2A1=2A22A1=2A2A1

∵ d 0 = A 2 − A 1 \because d_0 = A_2 - A_1 d0=A2A1

∴ d 1 = d 0 2 \therefore d_1 = \frac{d_0}{2} d1=2d0

即,每次产生新数后,公差 d d d 就除以 2 2 2

到此,思路就已经出来了。

本题像是一个二分,每次二分子区间,只取左或右区间,每次将 d d d 除以 2 2 2,判断其奇偶。

开始,子区间数量为 1 1 1,没有新数。

第一次,子区间数量为 2 2 2,原来的新数为 0 0 0,产生的新数为 1 1 1,共产生 1 1 1 个数。

第二次,子区间数量为 4 4 4,原来的新数为 1 1 1,产生的新数为 2 2 2,,共产生 3 3 3 个数。

第三次,子区间数量为 8 8 8,原来的新数为 3 3 3,产生的新数为 4 4 4,共产生 7 7 7 个数。

可以发现,设答案为 a n s ans ans,则 a n s i = 2 a n s i − 1 + 1 ans_i = 2ans_{i-1}+1 ansi=2ansi1+1

Code:

#include <cstdio>
int t;
long long n, a, d;
int main() {
	scanf("%d", &t);
	while(t--) {
		scanf("%lld %lld %lld", &n, &a, &d);
		long long ans = 0;
		while(!(d & 1)) {
			ans = (ans << 1) + 1;
			d >>= 1;
		}
		printf("%lld\n", ans * (n - 1));
	}
	return 0;
}   
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值