题目翻译
一个长度为 $n$ 的数组,最多 $n$ 次询问,输出数组元素。
询问:每次输出 ? x y
,返回 $x+y$ 的值。
输出:输出 !
之后空一格,正常输出数组元素。
题目思路
小学数学知识。
我们先询问 $x+y$ 的值,在询问 $x+z$ 的值,最后询问 $y+z$ 的值。
恰好每个数出现两次,把总和除以二,得到 $x+y+z$。
知道三数总和,知道两两之和,相减求 $3$ 个数的值。
接着处理余下的数。
整除 $3$,输出。
余 $2$,查询两个数的和,在随机找一个数搭配算出来。
余 $1$,随便找数搭配算。
AC 代码
void solve()
{
int n;
cin>>n;
int a[n+1];
for(int i=1;i<=n-n%3;i+=3)//先3个一组解决
{
int x,y,z;
cout<<"? "<<i<<" "<<i+2<<endl;
fflush(stdout);
cin>>x;
cout<<"? "<<i<<" "<<i+1<<endl;
fflush(stdout);
cin>>y;
cout<<"? "<<i+1<<" "<<i+2<<endl;
fflush(stdout);
cin>>z;
int sum=x+y+z;
sum/=2;
a[i+1]=sum-x;
a[i+2]=sum-y;
a[i]=sum-z;
}
//解决剩下的
if(n%3==2)
{
cout<<"? "<<n-1<<" "<<n<<endl;
fflush(stdout);
int x,y;
cin>>x;
cout<<"? "<<1<<" "<<n<<endl;
fflush(stdout);
cin>>y;
a[n]=y-a[1];
a[n-1]=x-a[n];
}
if(n%3==1)
{
cout<<"? 1 "<<n<<endl;
fflush(stdout);
int x;
cin>>x;
a[n]=x-a[1];
}
cout<<"! ";
for(int i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
}