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;
}

原文地址:https://www.cnblogs.com/lyfoi/p/9485066.html

时间: 2024-07-30 11:51:51

Codeforces Round #501 (Div. 3) D Walking Between Houses的相关文章

Codeforces Round #501 (Div. 3) F. Bracket Substring

题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60949 ....看不懂 设dp[i][j][l]表示前i位,左括号-右括号=j,匹配到l了 状态转移,枚举下一个要填的括号,用next数组求状态的l,分别转移 代码 #include<bits/stdc++.h> using namespace std; const int maxn = 207;

Codeforces Round #501 (Div. 3) A Points in Segments

翻译 现在有一个数轴,上面会有\(M\)个点,标号为\(1\)到\(N\),现在给你在数轴上的条\(N\)线段的起始与终止的点,问哪几个点没有被这样线段覆盖,从小到大输出. 思路 签到题目.感觉几乎和一道题一样:校门外的树,撞题是很尴尬.思路差不多,即为开一个数组,全部赋值为\(0\),输入的线段的时候,将其起点与终点的全部的点赋值为\(1\),最后跑一下看看那些为\(0\)的点就完事了. Code #include<iostream> using namespace std; int boo

Codeforces Round #501 (Div. 3) B Obtaining the String

翻译 给你两个字符串\(s\)与\(t\),你每次可以交换字符串\(s\)种相邻两个字符,请你输出字符串\(s\)变成\(t\)的步骤(如果输出\(k\),代表交换了\(k\)与\(k+1\)),如果有多组解,随意输出一种即可. 思路 这道题一开始考虑复杂了,导致我发奋图强到\(11:40\)才\(A\)掉,我\(12:00\)必须睡觉因为明天有课\(www\). 实际不难,这题是\(SPJ\),我是这么想的:我们都知道任意\(1\)个字符可以通过交换相邻的两个字符来跑遍整个字符串. 进而可以得

Codeforces Round #249 (Div. 2)-D

这场的c实在不想做,sad. D: 标记一下每一个点8个方向不经过黑点最多能到达多少个黑点. 由题意可知,三角形都是等腰三角形,那么我们就枚举三角形的顶点. 对于每一个定点,有8个方向可以放三角形. 然后枚举8个方向,然后枚举腰的长度.然后判断是否可行. #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h>

Codeforces Round #360 (Div. 2) D 数学推导 E dp

Codeforces Round #360 (Div. 2) A  == B  水,但记一下: 第 n 个长度为偶数的回文数是  n+reverse(n). C    dfs 01染色,水 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i

Codeforces Round #177 (Div. 2) 题解

[前言]咦?现在怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2.至于怎么决定场次嘛,一般我报一个数字A,随便再拉一个人选一个数字B.然后开始做第A^B场.如果觉得机密性不高,来点取模吧.然后今天做的这场少有的AK了.(其实模拟赛只做完了4题,最后1题来不及打了) 等等,话说前面几题不用写题解了?算了,让我难得风光一下啦. [A] A. Polo the Penguin and Segments time limit per test 2 seconds mem

Codeforces Round #617 (Div. 3) 题解

目录 Codeforces Round #617 (Div. 3) 题解 前言 A. Array with Odd Sum 题意 做法 程序 B. Food Buying 题意 做法 程序 C. Yet Another Walking Robot 题意 做法 程序 D. Fight with Monsters 题意 做法 程序 E1. String Coloring (easy version) 题意 做法 程序 E2. String Coloring (hard version) 题意 做法

[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F

[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F 1296A - Array with Odd Sum 思路: 如果一开始数组的sum和是奇数,那么直接YES, 否则:如果存在一个奇数和一个偶数,答案为YES,否则为NO 代码: int n; int a[maxn]; int main() { //freopen("D:\\code\\text\\input.txt","r",stdin); //freopen(

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i