这个题做的真是惨,场上写出了各种bugQAQ。
有一个注意的地方是数据会爆int。
两种做法,第一种假设第一个数是x,那么依次可推出后面的数,然后求和(和为(1+n)*n/2)解得x。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=2e5+10;
typedef long long int ll;
ll n;
ll arr[maxn];
int vis[maxn];
bool Judge(ll x){
vis[x]=1;
for(int i=1;i<n;i++){
x+=arr[i];
if(x>n || x<1 || vis[x]) return false ;
vis[x]=1;
}
return true ;
}
int main()
{
while(scanf("%I64d",&n)!=EOF){
ll sum=0,ans=0,a;
memset(vis,0,sizeof(vis));
for(int i=1;i<n;i++){
scanf("%I64d",&a);
arr[i]=a;
sum+=a;
ans+=sum;
}
ll cnt=(1+n)*n/2;
cnt-=ans;
if(cnt%n==0){
ll x=cnt/n;
if((x>=1 && x<=n) && Judge(x)){
printf("%I64d ",x);
for(int i=1;i<n;i++){
x+=arr[i];
printf("%I64d%c",x,i==n-1?'\n':' ');
}
}else printf("-1\n");
}else printf("-1\n");
}
return 0;
}
第二种是随便设第一个数为已知数,然后根据输入递推后面的数,找出其中最小的,然后使其变成1即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=(100000<<1)+5;//这个地方加括号
int n,x;
int arr[maxn],vis[maxn];
int main(){
scanf("%d",&n);
arr[1]=1;
int num=1,minnum=1;
for(int i=2;i<=n;i++){
scanf("%d",&x);
num+=x;
minnum=min(minnum,num);
arr[i]=num;
}
int cnt=1-minnum;
for(int i=1;i<=n;i++){
arr[i]+=cnt;
if(arr[i]<1 || arr[i]>n || vis[arr[i]]){//这个地方要先判断是否构成排列来避免爆int
printf("-1\n");
return 0;
}
vis[arr[i]]=1;
}
for(int i=1;i<=n;i++)
printf("%d%c",arr[i],i==n?'\n':' ');
return 0;
}