题目链接
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;
}
反思
- 这题直接想当然取最小球数盒子位置进行模拟,而没有想到可能出现多个最小球数盒子
- 没有深入思考到底该取哪个盒子
- 下次可以想想极端情况来排除一些错误