这是一个互动的问题。简单版和困难版的唯一区别是题数的限制。有n个玩家,从1到n,可以保证n是3的倍数。其中,有k个冒名顶替者和n-k个船员。冒名顶替者的数量,k,不是已知的。可以保证k <在每个问题中,你可以选择三个不同的整数a, b, c (1s a, b, c S n),然后问:“在标记为a, b和c的玩家中,冒名顶替者更多还是组员更多?”如果冒名顶替者比船员多,你将得到整数O,否则是1。在问最多2n个问题后,找出冒名顶替者的数量k和冒名顶替者的指数。评审团是自适应的,这意味着冒名顶替者的指标可能不是事先确定的,可以取决于你的问题。可以保证在任何时候至少有一组冒名顶替者满足约束条件和您的问题的答案。输入每个测试包含多个测试用例。第一行包含测试用例的数量t (1 S t 100)。测试用例的描述如下。每个测试用例的第一行也是唯一一行包含一个整数n (6 < n < 104, n是3的倍数)——玩家的数量。它保证所有测试用例的n的和不超过2- 104。
Example
input
Copy
2 6 0 1 9 1
output
Copy
? 1 2 3 ? 3 4 5 ! 3 4 1 2 ? 7 1 9 ! 4 2 3 6 8
题解:
像题中所给的
? 1 2 3
? 3 4 5
只一个共同数,是得不到什么有用的信息的
所以我们这样询问
假设a,b,c,d
? a b c
? b c d
如果询问结果相同则不用考虑,
否则我们可以知道
假设? a b c 为1
?b c d为0
b c肯定有一个0 和一个 1,否则询问不会不同
那么我们就可以确定a为1 d为0
确定了两个数,剩下的n - 2个数,每次直接与这两个数进行询问即可,若为0,肯定是我们需要的
总共询问数为n + n - 2,
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
int res[100050];
void solve()
{
int n;
cin >> n;
vector<int> ans;
for(int i = 0;i < n;i++)
{
cout <<"? "<<i + 1<<" "<<(i +1)%n + 1<<" "<<(i+2)%n + 1<<"\n";
cin >> res[i];
}
for(int i = 0;i < n;i++)
{
if(res[i] != res[(i + 1)%n])
{
if(res[i] == 0)
{
ans.push_back({i + 1});
}
else
{
ans.push_back({(i + 3)%n + 1});
}
for(int j = 0;j < n;j++)
{
if(j != i&&j != (i + 3)%n)
{
cout <<"? "<<i + 1<<" "<<(i + 3)%n + 1<<" "<<j + 1<<"\n";
int p;
cin >> p;
if(p == 0)
{
ans.push_back(j + 1);
}
}
}
break;
}
}
cout << "! "<<ans.size();
for(auto x:ans)
{
cout << " "<<x;
// printf(" %d",x);
}
cout <<"\n";
}
//1 2 4
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
// scanf("%d",&t);
while (t--)
{
solve();
}
return 0;
}
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//0 1 1 1 1
//0 1 1 1 1