Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2) D. Take a Guess (交互,位运算性质)
- 题意:交互题,有一组长度位\(n\)的数,你最多可以询问\(2*n\)次,每次可以询问两个位置\(i\)和\(j\),问他们的and或or值,求数组中第\(k\)大的数.
- 题解: 对于两个数\(a\)和\(b\),\(a\)&\(b\)和\(a\)|\(b\),不难发现\(a+b\)=\(a\)&\(b\)+\(a\)|\(b\).因为\(a\)&\(b\)表示的是\(a\)和\(b\)共同的一,而\(a\)|\(b\)是不进位的加法,于是现在我们要让没有进位的位置进位,而\(a\)&\(b\)刚好就是需要进位的位置,于是他们相加就能得到\(a+b\),那这样的话我们就可以得到\(a_1+a_2,a_1+a_3,...,a_1+a_n\)的值,在求出\(a_2+a_3\)的值,刚好\(2*n\)次,得到这个数组所有的值.
- 代码:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
int n,k;
int a[N];
int sum[N];
int main() {
scanf("%d %d",&n,&k);
int x,y;
printf("and 2 3\n");
fflush(stdout);
scanf("%d",&x);
printf("or 2 3\n");
fflush(stdout);
scanf("%d",&y);
sum[1]=x+y;
for(int i=2;i<=n;++i){
printf("and 1 %d\n",i);
fflush(stdout);
scanf("%d",&x);
printf("or 1 %d\n",i);
fflush(stdout);
scanf("%d",&y);
sum[i]=x+y;
}
a[1]=(sum[2]+sum[3]-sum[1])/2;
for(int i=2;i<=n;++i) a[i]=sum[i]-a[1];
sort(a+1,a+1+n);
printf("finish %d\n",a[k]);
fflush(stdout);
return 0;
}
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮