CF727C Guess the Array

注:本文含交互题 endl 与 fflush 不同种类的配合使用效果的 测试(见 “四”)

一. 审题:

1. 前提条件:

  • 一个数 nn 代表数组中数的个数。

2. 询问 & 输入:

  • 询问:

    输出两个数 xxyy 。代表询问 axa_xaya_y 的和。

    格式:? x y

  • 输入:

    读入一个数代表这两个数的和。

3. 输出:

  • 数组中所有数的值。格式:! a[1] a[2] a[3] ... a[n]

二. 思路

1. 思考解法

我们可以不一口气把 nn 次都询问完(当然最后肯定是都要询问完的),既然 nn 个数询问 nn 次一定有解,那么我们可以先询问 a1+a2a_1+a_2a2+a3a_2+a_3 以及 a3+a1a_3+a_1 。这样就能先计算出 a1a_1a2a_2 以及 a3a_3

只要有了一个数的具体值,我们每询问一次就可以算出一个数的具体值,这样一气呵成,避免了一口气询问完后堆积过多条件无从下手的情况。

2. 具体实现

  1. 前三个数:

    解法有很多,如

        {x+y=ay+z=bz+x=c\ \ \ \ \begin{cases}x+y=a\\y+z=b\\z+x=c\end{cases}

    2x+2y+2z=a+b+c\Longrightarrow 2x+2y+2z=a+b+c

    x+y+z=a+b+c2\Longrightarrow x+y+z=\dfrac{a+b+c}{2}

    x=a+b+c2b\Longrightarrow x=\dfrac{a+b+c}{2}-b

    yyzz 同理。

  2. 剩下的数:

    接下来询问a1+a4a_1+a_4a1+a5a_1+a_5 . . . a1+ana_1+a_n

三. 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<bits/stdc++.h>
using namespace std;
const int MAXn = 5000;

int n;
int add12,add13,add23; //addxy:第x个和第y个数的和
int add[MAXn + 10]; //add[x]:第1个和第x个数的和
int first; //第一个数的值
int main() {
scanf("%d", &n);
cout << "? 1 2" << endl; scanf("%d", &add12);
cout << "? 2 3" << endl; scanf("%d", &add23);
cout << "? 1 3" << endl; scanf("%d", &add13);//这里用了endl就不需要fflush(stdout)了
first = (add13 - add23 + add12) >> 1;//读入前三个数间两两值得和,并计算第一个数
for (int i = 4 ; i <= n; ++i) {
cout << "? 1 " << i << endl;
scanf("%d", &add[i]);
}//读入第1个数和第4-n个数间两两的值
cout << "! " << first; fflush(stdout);
cout << ' ' << add12 - first; fflush(stdout);
cout << ' ' << add23 - add12 + first; fflush(stdout);
for(int i = 4; i <= n; ++i) {
cout << ' ' << add[i] - first;
}
}

四. endl 与 fflush

对交互题来说,弄清楚 endlfflush 怎么用格外重要。不多废话了,直接摆上测试结果:

结论:endl 后面 不用跟 fflush,但如果没有 endl (或是用 printf)要加上 fflush(stdout)