题解:CF1015D Walking Between Houses

题解:CF1015D Walking Between Houses

算法

模拟,分类讨论

分析

首先,设每步走的距离为 \(t_i\),我们发现 \(t_i\) 应是满足 \(1\le t_i\le n-1\) 的。那么就很容易推出 NO 的情况:

  • \(s<k\) 时,由于每一步都要至少走一个单位,所以 \(k\) 次步数肯定用不完,而题目要求恰好 \(k\) 次;
  • \(\frac{s}{k}>n-1\) 时,此时我们把每一步都撑到了最大的距离也就是 \(n-1\) 个单位,但仍不满足要求,所以判负。

判完 NO 后,余下的就都是 YES 的情况,考虑怎么构造方案。

  • 如果 \(k\mid s\),容易想到一种构造方案为 \(\frac{s}{k},1,\frac{s}{k},…,1,\frac{s}{k}(,1)\)

  • 如果 \(k\nmid s\),说明 \(s\div k\) 存在余数,那我们以上一种情况的方式处理后将余数加上即可。为了方便处理,我采用了上取整再将多走的距离减去的方法。这时多走的距离就是 \(\left\lceil\dfrac{s}{k}\right\rceil\times k-s\)。注意,在中间的某处减去一个单位的距离相当于少走了两个单位的距离(如 \(1,3,1\) 变为 \(1,2,1\)),那么在余数为奇数时,将中间的减完后会剩 \(1\),我们需要在结尾处理,此时需分类讨论。

    1. \(k\) 为偶数时,原本 \(k\) 回到开头 \(1\),但因为我们处理剩下多走了 \(1\) 个单位的距离,所以我们少走一个应回到 \(2\)
    2. \(k\) 为奇数时,原本 \(k\) 会走到后面的 \(\frac{s}{k}\) 处,但因为我们多走了 \(1\) 个单位,所以我们将结尾走到的位置减 \(1\)

最终输出答案即可,注意要开 long long,不然会 Wrong answer on test 8

示例代码

#include<bits/stdc++.h>
using namespace std;
#define int long long 
namespace Ryan
{
    const int N=2e5+5;
    vector<int> v;
    int n,k,s;
    signed work()
    {
        cin>>n>>k>>s;
        if(k>s||s*1.0/k>(n-1))
        {
            cout<<"NO"<<endl;
            return 0;
        }
        for(int i=1;i<=k;i++)
        {
            if(i&1)
                v.push_back(ceil(s*1.0/k)+1);
            else 
                v.push_back(1);
        }
        if(s%k)
        {
            int ss=ceil(s*1.0/k)*k-s;
            // cout<<ss<<"**\n";
            for(int i=1;i<=k&&ss-2>=0;i+=2)
            {
                ss-=2;
                v[i-1]--;
            }
            if(ss)
            {
                if(k&1)
                    v[k-1]-=1;
                else 
                    v[k-1]+=1;
            }
        }
        cout<<"YES"<<endl;
        for(auto it:v)
            cout<<it<<" ";
        return 0;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    return Ryan::work();
}
posted @ 2024-08-01 13:32  Ryan_Adam  阅读(3)  评论(0编辑  收藏  举报