Codeforces Round #501 (Div. 3) D Walking Between Houses
Posted lyfoi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #501 (Div. 3) D Walking Between Houses相关的知识,希望对你有一定的参考价值。
翻译
给你一条数轴(出题人很喜欢数轴啊),上面有排列着(n)个点,编号为(1)到(n)(你开始在(1))。每次你要从一个点移动到另一个点(可以重复)。移动距离为两点坐标之差的绝对值,问你是否能否在(k)次机会内里一共移动(s)距离,并输出方案。
思路
第四题还是比较难的,赛后想了几分钟时才有头绪。
毫无疑问还是贪心(出题人很喜欢贪心啊)!那么我们分类讨论,先看不合法的情况
无论如何走你也走不到那个距离
无论如何走你也会走超那个距离
看来只要能走到那个距离除外都是不合法的,因此就一个走超和走不到(我没废话!)。
那么如何解决?很简单,走不到就是每次你从最左边走到最右边,再从最右边走到最左边,这样循环下去,一直到你走完了还不到。
走超了就是你每次走一个距离,进行(k)次后还是大于(s)。
那么这两个代码好写极了,不用我教你吧(^_^)。
到了合法的情况,受到不合法的启发,我们可以想到这样的方法:每一次啊,先从最左边走到最右边,再从最右边走到最左边,循环下去,一直到你剩下的距离不足(n-1)((n-1)就是数轴两个端点间的距离)的时候啊,直接走完即可(由于在此期间你只会位于数轴的两个端点)。
但是不会那么简单的(QAQ),直接走完可不行啊,如果要走(32)那么远,(4)下子走完,数轴有(11)个点。照我们说的,当还有两个长度的时候,我们一步走完,呀!怎么还有一下!!
所以说,我们可以这样想:当剩下的距离不足(n-1)的时候,我们尝试分成多部走,很多种方法,我的有点麻烦,某位大佬写的是:走(s-k)((s)是剩下的距离)的步数。感觉自己恍然大悟了(不懂你可以算算,由于是(s-k),这样就巧妙的拆分成了多部分)!
一定要用long long
((CF)的题就这个尿性)!
恐怕上述的方法是最简单的方法之一了吧,上代码(有两个细节在代码里注释了):
Code
#include<iostream>
using namespace std;
int main()
{
long long n,k,s,a=1;
cin>>n>>k>>s;
if(s>(n-1)*k||k>s)
return cout<<"NO"<<endl,0;
cout<<"YES"<<endl;
while(k--)
{
int r=min(s-k,n-1);//选区n-1与s-k中最小的,因为当s-k比n-1大的时候,我们要先消去
s-=r;
if(a+r<=n)//看看往哪个方向走。
a+=r;
else a-=r;
cout<<a<<" ";
}
return 0;
}
以上是关于Codeforces Round #501 (Div. 3) D Walking Between Houses的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #501 (Div. 3) F. Bracket Substring
Codeforces Round #501 (Div. 3) ABDE1E2
Codeforces Round #501 (Div. 3) 翻船记
Codeforces Round #501 (Div. 3) B Obtaining the String