Codeforces Round #158 (Div. 2)C. Balls and Boxes(模拟)

题目链接

http://codeforces.com/contest/260/problem/C

题目大意

有n个盒子(1-n排好) 盒子里有若干球,任意选择一个盒子i(这个盒子里保证有球),将球取出,一个一个放入i+1, i+2 … 盒子中,直到取出的球都放完(如果放了第n个盒子, 接下来从1号盒子开始放
现在告诉你放完后各个盒子里球的数量 和 最后一个球放入的盒子的下标x, 问你放之前每个盒子里分别有多少球

思路

你想的没错, 这是道模拟水题, 但是既然你在看我这篇博客, 想必你可能遇到了和我一样的问题
开始的时候我想当然地找到最小数量的盒子位置,开始模拟, 数量最小的盒子一定是把球都取出来给别的盒子的盒子i, 因为它的球都分给了别的盒子
然而这却有一个bug, 如果求数量最小的盒子不只一个, 我们就无法确定该从哪个盒子开始模拟
假如我们把一个离x远的(这里远指的是沿着放球路径)盒子开始模拟,那么如果有离x近的盒子(与那个盒子有相同球数)将会多放球,将会与最后给出的球数矛盾,这在反向模拟的时候更明显,因为这一路径上会比路径外的盒子多减一个球,该盒子球数将会小于0
由此我们可以想到,我们应给从x开始, 反向找离x最近的最小球数的盒子

代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll a[100005];

int main()
{
    ll n, x, m = 0x3f3f3f3f;
    scanf("%I64d %I64d", &n, &x);
    for(int i=1; i<=n; ++i)
    {
        scanf("%I64d", a+i);
        m = min(m, a[i]);
    }

    ll sum = 0;
    while(a[x] != m)
    {
        --a[x];
        ++sum;
        --x;
        if(x == 0)x=n;
    }
    for(int i=1; i<=n; ++i)
    {
        if(i != x)printf("%I64d ", a[i] - m);
        else printf("%I64d ", n*m + sum);
    }
    return 0;
}

反思

  • 这题直接想当然取最小球数盒子位置进行模拟,而没有想到可能出现多个最小球数盒子
  • 没有深入思考到底该取哪个盒子
  • 下次可以想想极端情况来排除一些错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值