【C++】交互题

交互题这类型不同于普通的题。
可以理解为有个问题需要你解决,你通过输入某些东西。
表示你要问系统的问题,这时系统会回答你的问题。
在代码中的回答方式就是会输入某个东西就是系统给你的答案,通过这些信息你可以得到问题的解。
你是不可以自己测试的,只能提交给系统测试。
有个东西需要用到C++中的 fflush(stdout); ,这个东西是用来清空输出缓存区的。
因为你一直提问,一直输出,就需要清空输出缓存区。不然就有一些异常。

举一个最简单的例子:
猜数字我内心突然想到一个1到100之间的整数x。
现在我让你来猜,最多给你7次机会,每次你可以猜一个数字。
我会告诉你是大了,还是小了,还是猜对了。
方法就是二分。

下面给出几题简单的交互题。

1.Bear and Prime 100

https://codeforces.com/problemset/problem/679/A

vjudge上也可以做:https://vjudge.net/problem/CodeForces-679A

在这里插入图片描述
题目大意:有一个你未知的在2到100之间的整数,现在判断出他是质数还是合数。你最多可以提20个问题。
每个问题: x 。意思就是你问系统那个未知数能否被x整除,如果能整除,系统会输出yes,否则no。
最后的答案: prime 或 composite

思路:把50以内的质数(外加4,9,25,49)都去提问一遍,如果有大于等于2次被整除,那么就是合数。否则就是质数。

代码:

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

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

#define R                  register int
#define re(i,a,b)          for(R i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))

using namespace std;

typedef long long ll;

int a[19]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,4,9,25,49};
int sum;

int main() {
    for(int i=0; i<19; i++) {
        printf("%d\n",a[i]);
        fflush(stdout);
        string s;
        cin >> s;
        if(s=="yes") sum++;
        if(sum==2) {
            printf("composite\n");
            return 0;
        }
    }
    printf("prime\n");
    return 0;
}

2.Lost Numbers

原题:https://codeforces.com/contest/1167/problem/B
vjudge: https://vjudge.net/problem/CodeForces-1167B

在这里插入图片描述
题目大意:有6个整数,分别是4,8,15,16,23,42,但是你不知道他们的顺序。现在你的任务就是要求出它们的顺序。
提问题的方法: 输出 ? i j ,意思就是你在问系统a[i]*a[j]的乘积是多少?
你最多可以提4次问题,然后就你要确定他们的顺序。
最后,如果你得到答案了,那么你就输出 ! a[1] a[2] a[3] a[4] a[5] a[6]

思路:任意两个数的乘积都是不同的(本题的关键)
可以提问:
a[1]*a[2]
a[2]*a[3]
a[3]*a[4]
a[4]*a[5]
也可提问:
a[1]*a[2]
a[2]*a[3]
a[4]*a[5]
a[5]*a[6]

代码:

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

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

#define R                  register int
#define re(i,a,b)          for(R i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))

using namespace std;

typedef long long ll;

int a[7]={0,4,8,15,16,23,42};
int b[5];

int main() {
    for(int i=1; i<=4; i++) {
        printf("? %d %d\n",i,i+1);
        fflush(stdout);
        scanf("%d",&b[i]);
    }
    while(1) {
        if(a[1]*a[2]==b[1] && a[2]*a[3]==b[2] && a[3]*a[4]==b[3] && a[4]*a[5]==b[4]) {
            printf("!");
            for(int i=1; i<=6; i++) printf(" %d",a[i]);
            break;
        }
        next_permutation(a+1,a+7);
    }
    return 0;
}

3.Strange Device

原题:https://codeforces.com/problemset/problem/1270/D
vjudge:https://vjudge.net/problem/CodeForces-1270D

在这里插入图片描述
题目大意:n,k是已知的,m是未知的。有n个互不相同的数(不知道的)。
你最多有n次提问的机会。
每次提问:你可以具体指出某k个位置,系统会告诉你这k个位置上第m小的数是多少。
求m。

思路:询问k+1次,针对a[1]…a[k+1] 。
第一次询问 2…k+1
第二次询问 1,3,4…k+1
第三次循环 1,2,4,5…k+1

我们发现每次的答案一定是a[1]到a[k+1]里面的第m小或者第m+1小的数。
因为如果少的是比第m小的数大的数,那么答案就是第m小的数。
如果少的是比第m小的数小于等于的数,那么答案就是第m+1小的数。
探究第m小的数出现了几次? k+1-m个。
第m+1小的数出现了几次? m个。
所以答案就是k+1次询问里面大的那个数出现的次数 。

代码:

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

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

#define R                  register int
#define re(i,a,b)          for(R i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))

using namespace std;

typedef long long ll;

int const N=505;

int n,k;
int a[N],vis[N];

int main() {
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++) {
        if(i>k+1) break;
        printf("? ");
        for(int j=1; j<=k+1; j++) if(j!=i) printf("%d ",j);
        fflush(stdout);
        int p,num;
        scanf("%d%d",&p,&num);
        a[p]=num;
        vis[p]++;
    }
    int mx=0,p=0;
    for(int i=1; i<=n; i++) {
        if(mx<a[i]) mx=a[i],p=i;
    }
    printf("! %d",vis[p]);
    return 0;
}

发布了34 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Ljnoit/article/details/104155794