本题所有程序默认开启O2,否则超时。这不是正解,但是比正解简洁明了,代码可读性强,但是不开O2超时。如有能力,建议学习正解。
另:题面有一个地方不太清楚:当满足 \(m<k\) 时,若仍有剩余,要放到下一个队伍里去。
根据题意,我们不难想到,设 \(ans_i\) 表示第 \(i\) 个队伍有多少人,那么,我们就不难想到一直放下去,知道满足条件为止。
但是注意到当到达第 \(n\) 个队伍的时候要逆序(i.e. \(n->(n-1)->...->2->1->2->...->(n-1)->n...\))。所以我们记一个flag
变量,当flag=0
的时候,说明是正序,否则倒序。然后设 \(now\) 表示现在到了第 \(num\) 个队伍,若 \(now=n\) 则另flag=1
,若 \(now=1\) 则令flag=0
。
需要注意在flag
变动时看一下当前 \(m\) 是否小于 \(k\) 。
参考代码(91points):
#include <cstdio>
int now=1, n, k, m, ans[200010], flag;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0' , ch=getchar();
return s*w;
}
int main(void) {
n=read(), k=read(), m=read();
while(1) {
if(now==n) {
flag=1; //标记从现在开始就是倒序
ans[now] += k; //加上
m -= k; //减去
now--; //倒序则不断把now减一,模拟了倒序的过程
if(m<k) { //判断是否满足条件
ans[now] += m;
break;
}
continue; //不用继续进行后面的操作了
}
else if(now==1) {
flag=0;
ans[now] += k;
m -= k;
now++;
if(m<k) {
ans[now] += m;
break;
}
continue;
} //同上
if(m<k) { //这里仍然要判断
ans[now] += m;
break;
}
ans[now] += k;
m -= k;
if(flag) --now; //如果当前标记为倒序,则now--
else ++now; //否则now++
}
//printf("QAQ\n"); //QAQ
for(int i=1;i<=n;i++)
printf("%d ", ans[i]);
return 0;
}
91分,不是因为TLE,而是因为WA!为啥呢?
上面那份代码的hack数据(感谢@metaphysis 的提供):
3 2 4
这份数据正确的结果应该是2 2 0
,但是上面那份程序跑出了2 0 2
!
为什么会出现这样的情况呢?原因出在判断 \(now\) 那里,以第一个判断为例:
if(now==n) {
flag=1;
ans[now] += k;
m -= k;
now--;
if(m<k) {
ans[now] += m;
break;
}
continue;
}
假如说正好分配完,没有多余,那么上面那份代码就出现了一个致命错误。为了帮助理解,我们演示一遍(人脑模拟gdb 233):
现在now=n, k=2, m=0
:
flag=1
(没啥好说的)
ans[now] += k
(看到问题了么?明明已经没有人了,但是还是加了一个不存在的 \(k\) )
m-=k
(问题严重了!现在 \(m=-2\) !)
now--
(导火索,现在去前面一个队伍了)
if(m<k) {
(进入)
ans[now] += m
(注意,这里是把前面一个队伍加上一个人(相当于减去))
break;
(跳出while
循环)
我们发现,我们把 \(ans_n\) 平白无故地加上了两个人;而把 \(ans_{n-1}\) 平白无故地减去了两个人(总人数虽然没变,但是答案已经错了)。
如果您可以明白上面那套东西,解决办法也就很自然了:提前判断是否满足条件,就可以解决这个问题。
最终AC代码(再次提醒开了O2)
#include <cstdio>
int now=1, n, k, m, ans[2000010], flag;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0' , ch=getchar();
return s*w;
}
int main(void) {
n=read(), k=read(), m=read();
while(1) {
if(now==n) {
if(m<k) {
ans[now] += m;
//printf("Now we need break and now The 'm'=%d\n", m);
break;
} //提前判断即可。
flag=1;
ans[now] += k;
//("now=%d,OK! a[%d]=%d\n", n, n, ans[n]);
m -= k;
now--;
continue;
}
else if(now==1) {
if(m<k) {
ans[now] += m;
//printf("Now we need break and now The 'm'=%d\n", m);
break;
}
flag=0;
ans[now] += k;
//printf("now=1,OK! a[1]=%d\n", ans[1]);
m -= k;
now++;
continue;
}
if(m<k) {
ans[now] += m;
//printf("Now we need break and now The 'm'=%d\n", m);
break;
}
ans[now] += k;
m -= k;
//printf("now=%d,OK! a[%d]=%d\n", now, now, ans[now]);
if(flag) --now;
else ++now;
}
//printf("QAQ\n");
for(int i=1;i<=n;i++)
printf("%d ", ans[i]);
return 0;
}