CF1409C - Yet Another Array Restoration

题目地址

https://codeforces.com/problemset/problem/1409/C

题目描述

给定 n , x , y n,x,y n,x,y,请构造出一个序列 a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,,an,使 x , y ∈ { a i } x,y \in \{a_i\} x,y{ai},且排序后 a 2 − a 1 = a 3 − a 2 = ⋯ = a n − a n − 1 a_2-a_1=a_3-a_2=\cdots=a_n-a_{n-1} a2a1=a3a2==anan1,并且使 max ⁡ i = 1 n a i \max_{i=1}^n a_i maxi=1nai 最小。请求出这个序列。

解题思路

根据题目描述我们可以得知,要生成一个数量为 n n n的等差数列,数列中要包含 x , y x,y x,y,并且要求数列中的第1项大于0,最后一项最小。

首先要找到公差 d d d,数列中要包含 x , y x,y x,y,l。因此枚举1y-x中能整除y-x数即可。

对于不同的公差 d d d,设在公差 d d d x x x y y y k k k项。考虑下面几种不同的情况:

  1. k = n k=n k=n,直接输出答案, a 1 = x , a n = y a_1=x,a_n=y a1=x,an=y
  2. k > n k>n k>n,直接跳过此公差
  3. k < n k<n k<n,设 x x x之前在公差 d d d下,且大于 0 0 0 p r e pre pre 项:
    3.1 : p r e = 0 pre=0 pre=0时, a 1 = x a_1=x a1=x
    3.2 :当 p r e + k < = n pre+k<=n pre+k<=n a 1 a_1 a1为大于0的第 1 1 1项;
    3.3 : 当 p r e + k > n pre+k>n pre+k>n x x x前的项数就不能全部取完,只能前 x x x前的 n − k n-k nk项;
    得到 a 1 a_1 a1后,计算出 a n a_n an比较下大小即可

参考代码

#include <iostream>
using namespace std;
int main(){
	int t,n,x,y;
	cin>>t;
	while ( t-- ) {
		cin>>n>>x>>y;
		int temp = y-x;
		int ans=x+(n-1)*temp;	//数列最后一项
		int d=temp;		//公差
		
		//枚举所有可能的公差
		for ( int i=1; i <= temp; i++ ) {
			if( temp%i == 0 ) {
				//x和y之间的项数
				int num = temp/i + 1;
				if( num > n ) continue;
				if( num == n ) {
					ans = y;
					d = i;
					break;
				}
				//x为首项
				if( ans > x+(n-1)*i ){
					ans = x+(n-1)*i;
					d=i;	
				}
				
				//计算x之前的项数
				int num_pre = 0;
				num_pre = x / i;
				
				if( x%i == 0 ) num_pre = x/i - 1;
				if(num_pre<=0) continue;
				
				int a1,an;
				
				//判断x之前的项是否超过输出的项
				if( num_pre + num <= n){
					a1= x- ( num_pre )*i;
					an= a1 + (n-1)*i;
					
				
				}else{
					a1= x- ( n-num )*i;
					an= a1 + (n-1)*i;
				}		
				if(an<ans){
					ans=an;
					d=i;
				}			
			}
		}
		
		ans=ans-(n-1)*d;
		for ( int i=0; i<n-1;i++)
			cout<<ans+i*d<<" ";
		cout<< ans+ d*(n-1)<<endl;		
	}
	return 0;
}

总结

分析问题时,由题目给出的限制条件,在纸上先列出所有可能的情况,对其分类讨论;分类讨论时,先在大的方向进行分类,然后在大分类的基础再继续进行细分。比如这道题是以 x x x y y y之间在公差 d d d下能产生多少个数列项进行分类,在此基础上再继续细分下去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值