前置芝士:
c++ 中的整除:
设三个正整数分别为 $a$ , $b$ , $c$ ,且:
那么在 c++ 的运算中,会出现两种情况:
- $a \times b \ne c$ (也就是 c 不能整除 a 或 b )
- $a \times b = c$ (也就是 c 能整除 a 或 b )
那么在后面的程序中就会讲到怎么使用这两个性质
思路:
由于给出的是前缀和数组中的一部分,那么当前到上一个给出的前缀和的位置之间的数就可以求出来了。
首先先放查找从当前位开始给出的最近前缀和的位置的代码:
inline int findid(int s){
for(int i=s;i<=n;i++){
if(p[i]!=-1)return i;// 找到给出的前缀和则返回当前位置
}
return -1;// 否则返回 -1
}
设 $q$ 为当前前缀和的位置, $lq$ 为上一个前缀和的位置, $gc$ 是两个前缀和之差
那么就可以分 5 种情况:
$ lq=n $ (已经结束了):
if(lq==n)break;跳出循环
$ lq<n $ 且 $ q=-1 $ (最后的全都是 -1):
if(lq<n&&q==-1){ for(int i=lq+1;i<=n;i++)cout<<1<<" "; break; }$lq+1$ 到 $n$ 之间的数全部输出 1
$ gc=1 $ (两个前缀和之差为 1 ):
if(gc==1){ for(int i=lq+1;i<q;i++)cout<<0<<" "; cout<<1<<" "; }$lq+1$ 到 $q-1$ 之间的数输出 0 , $q$ 的位置输出 1
$ gc=0 $ (两个前缀和之差为 0 ):
if(gc==0){ for(int i=lq+1;i<=q;i++)cout<<0<<" "; }$lq+1$ 到 $q$ 之间的数输出 0
- 正常情况(每个值平均输出):
int qq=gc/(q-lq);// 取平均值 if(qq*(q-lq)!=gc){// 当不能整除时 for(int i=lq+1;i<q;i++)cout<<qq<<" ";//先输出向下取整的平均值 cout<<gc-(q-lq-1)*qq<<" ";//最后输出余下的值 }else{//当能整除时 for(int i=lq+1;i<=q;i++)cout<<qq<<" ";//直接输出平均值 }
思考题:为什么正常情况下必须每个值平均输出,而不能前面的值输出 0 ,最后的直接输出 $gc$ 的值?(答案在文章的最后面)
AC 代码就不放注释了,自己理解更好
CODE :
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
int x=0,f=1;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-')f=-1;
for(;c<='9'&&c>='0';c=getchar())
x=(x<<3)+(x<<1)+(c^48);
return (f==1?x:-x);
}
int t,n,p[100005],gc;
inline int findid(int s){
for(int i=s;i<=n;i++){
if(p[i]!=-1)return i;
}
return -1;
}
signed main(){
t=read();
p[0]=0;
while(t--){
n=read();
for(int i=1;i<=n;i++)p[i]=read();
int q=findid(1),lq=0;
if(q==-1){
for(int i=1;i<=n;i++)cout<<i<<" ";
cout<<endl;
}else{
while(1){
if(lq==n)break;
if(lq<n&&q==-1){
for(int i=lq+1;i<=n;i++)cout<<1<<" ";
break;
}
gc=p[q]-p[lq];
if(gc==1){
for(int i=lq+1;i<q;i++)cout<<0<<" ";
cout<<1<<" ";
}else if(gc==0){
for(int i=lq+1;i<=q;i++)cout<<0<<" ";
}else{
int qq=gc/(q-lq);
if(qq*(q-lq)!=gc){
for(int i=lq+1;i<q;i++)cout<<qq<<" ";
cout<<gc-(q-lq-1)*qq<<" ";
}else{
for(int i=lq+1;i<=q;i++)cout<<qq<<" ";
}
}
lq=q;
q=findid(q+1);
}
cout<<endl;
}
}
return 0;
}
思考题答案:
由于题目中的数据范围有这么一句话:
满足 $1 \le a_i \le 1000$
所以如果不平均地输出的话,可能会超过这个限制(只有 50 分)