Too Many Impostors (easy version)

12 篇文章 0 订阅

This is an interactive problem. The only difference between the easy and hard version is the limit on number of questions.

There are nn players labelled from 11 to nn. It is guaranteed that nn is a multiple of 33.

Among them, there are kk impostors and n−kn−k crewmates. The number of impostors, kk, is not given to you. It is guaranteed that n3<k<2n3n3<k<2n3.

In each question, you can choose three distinct integers aa, bb, cc (1≤a,b,c≤n1≤a,b,c≤n) and ask: "Among the players labelled aa, bb and cc, are there more impostors or more crewmates?" You will be given the integer 00 if there are more impostors than crewmates, and 11 otherwise.

Find the number of impostors kk and the indices of players that are impostors after asking at most 2n2n questions.

The jury is adaptive, which means the indices of impostors may not be fixed beforehand and can depend on your questions. It is guaranteed that there is at least one set of impostors which fulfills the constraints and the answers to your questions at any time.

Input

Each test contains multiple test cases. The first line contains the number of test cases tt (1≤t≤1001≤t≤100). Description of the test cases follows.

The first and only line of each test case contains a single integer nn (6≤n<1046≤n<104, nn is a multiple of 33) — the number of players.

It is guaranteed that the sum of nn over all test cases does not exceed 2⋅1042⋅104.

Interaction

For each test case, the interaction starts with reading nn.

Then you are allowed to make at most 2n2n questions in the following way:

"? a b c" (1≤a,b,c≤n1≤a,b,c≤n, aa, bb and cc are pairwise distinct).

After each one, you should read an integer rr, which is equal to 00 if there are more impostors than crewmates among players labelled aa, bb and cc, and equal to 11 otherwise.

Answer −1−1 instead of 00 or 11 means that you made an invalid query or exceeded the number of queries. Exit immediately after receiving −1−1 and you will see Wrong answer verdict. Otherwise you can get an arbitrary verdict because your solution will continue to read from a closed stream.

When you have found the indices of all impostors, print a single line "! " (without quotes), followed by the number of impostors kk, followed by kk integers representing the indices of the impostors. Please note that you must print all this information on the same line.

After printing the answer, your program must then continue to solve the remaining test cases, or exit if all test cases have been solved.

After printing the queries and answers do not forget to output end of line and flush the output buffer. Otherwise, you will get the Idleness limit exceeded verdict. To do flush use:

  • fflush(stdout) or cout.flush() in C++;
  • System.out.flush() in Java;
  • flush(output) in Pascal;
  • stdout.flush() in Python;
  • Read documentation for other languages.

Hacks

You cannot make hacks in this problem.

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

Note

Explanation for example interaction (note that this example only exists to demonstrate the interaction procedure and does not provide any hint for the solution):

For the first test case:

Question "? 1 2 3" returns 00, so there are more impostors than crewmates among players 11, 22 and 33.

Question "? 3 4 5" returns 11, so there are more crewmates than impostors among players 33, 44 and 55.

Outputting "! 3 4 1 2" means that one has found all the impostors, by some miracle. There are k=3k=3 impostors. The players who are impostors are players 44, 11 and 22.

For the second test case:

Question "? 7 1 9" returns 11, so there are more crewmates than impostors among players 77, 11 and 99.

Outputting "! 4 2 3 6 8" means that one has found all the impostors, by some miracle. There are k=4k=4 impostors. The players who are impostors are players 22, 33, 66 and 88.

思路:“卡一”,我们如何才能知道某个数是多少,就需要提前有1与0卡最后的一个数,那么这个数才是决定该组合的核心(数),返回是0那么这个数就是0,返回1这个数就是1,我们可以用这个数求出任何一个数。现在问题又来了,我们怎样才能有0与1呢?和“卡一”有异曲同工之妙,让两个组只错处来一个数(两个组都错处一个数),前提要知道:每个组的返回不可能全为1或全为0,因为1/3与2/3将它卡死了,取不到边界,便不可能全为0或1,所以返回的是0与1的组合。那么一定有一组相邻组的返回值不同,如果返回值不同那么它们这四个数可能是什么组合呢?如果中间两个重合的数相同,那么一定存在这两个组的值是相等的,因为中间两个数占了“主导地位”,组的值是根据两个相同数来判定的,所以相邻的两个组值不同就一定是中间的两个数不同,并且组的值也不同,所以两个组的值是由两端的数来决定的,所以第一组的值就是有该组存在的端点决定的,并且组的返回值是多少,该端点的值就是多少,由此可知一个0与一个1。这样便能求出全部数中的任何一个数(与就是全部数)要注意已知为0与1的这两数不要将它俩再查一遍。

代码实现:

破解“轮回”、“环”:一般用到此方法时,循环从1开始,(一定要区分题中的轮回是从即开始!是否有轮回!,然后分别带入每种方法求解即可)(从0开始的只需讲题目要求将样例带入即可便能得到关系(公式)(简单))一般是:环一般都循环一圈,不能用在类似“猴子选大王问题”这种题中,也就是将环中的数不断减少的环中)首先该方法需要将i=0开始,(结束是小于n的,取不到n)不管题目要求几轮回(即 n-cycle)都适用,即使是4轮回。那么每个数便是i+1(从0开始的循环不需要+1),输出的第一个是i+1第二个是(i+1)%n+1,第三个是(i+2)%n+1,之后依此类推便能得到全部的轮回。

记住每次有轮回的都需要除余

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int N=1e4+10;

void slove()
{
    int n;
    cin>>n;
    int res[N];
    for(int i=0;i<n;i++)
    {
        cout<<"? "<<i+1<<" "<<(i+1)%n+1<<" "<<(i+2)%n+1<<endl;
        cin>>res[i];
    }
    vector<int>vec;
    for(int i=0;i<n;i++)
    {
        if(res[i]!=res[(i+1)%n])
        {
            if(res[i]==0)vec.push_back(i+1);
            else vec.push_back((i+1)%n+3);
            for(int j=1;j<=n;j++)
            {
                if(j!=i+1&&j!=(i+1)%n+3)
                {
                    cout<<"? "<<i+1<<" "<<(i+1)%n+3<<" "<<j<<endl;
                    int x;
                    cin>>x;
                    if(x==0)vec.push_back(j);
                }
            }break;
        }
    }
    cout<<"! "<<vec.size();
    for(auto i:vec)
    {
        cout<<" "<<i;
    }cout<<endl;

}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        slove();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值