2022CCPC预选赛K
题面
题解
- 5000次都输的概率小,至少一场能赢
- 而本金很多,只需要每次都投入上一次投入金钱的两倍即可
代码
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
long long y,q,seed,cnt=1,x;
cin>>y>>q>>seed;
do {
cout<<cnt*y<<'\n';
fflush(stdout);
cnt*=2;
cin>>x;
}while(x!=2);
return 0;
}
题意
- 有一个[4,8,15,16,23,42]的排列,通过最多4次询问得出其排列
- 每次询问:可以询问两个位置i,j,返回ai*aj
题解
- 由于这些数两两乘积不同,所以只需按照(1,2),(2,3),(3,4),(4,5)去询问必然可以得到这6个数的排列
- 代码写法上,可以枚举所有排列,然后根据交互出来的回答验证某个排列的正确性
代码
#include <iostream>
#include <algorithm>
using namespace std;
int a[6]={4,8,15,16,23,42};
int b[6];
bool check() {
for(int i=0;i<4;i++)
if(a[i]*a[i+1]!=b[i])
return false;
return true;
}
int main() {
for(int i=0;i<4;i++) {
cout<<"? "<<i+1<<' '<<i+2<<'\n';
fflush(stdout);
cin>>b[i];
}
do {
if(check()) {
cout<<"! ";
for(int i=0;i<6;i++)
cout<<a[i]<<' ';
puts("");
}
}while(next_permutation(a,a+6));
return 0;
}
题意
- 有一个n的排列,能否通过最多2n次询问得到这个排列
- 每次询问:询问i,j,得到ai mod aj的值
题解
- 简化,n=2时,a=ask(1,2); b=ask(2,1);如果a>b说明a[1]<a[2],所以ans[1]=a,否则ans[2]=b
- 推广,用双指针一次确定两个指针中的一个数,直到最后没有确定位置的指针就是数值n所在的位置
代码
#include <iostream>
using namespace std;
const int N=1e4+10;
int ans[N];
int ask(int x,int y) {
cout<<"? "<<x+1<<' '<<y+1<<'\n';
fflush(stdout);
int k;
cin>>k;
return k;
}
int main() {
int n;
cin>>n;
int p=0;
for(int i=1;i<n;i++) {
int a=ask(p,i);
int b=ask(i,p);
if(a>b) {
ans[p]=a;
p=i;
}
else ans[i]=b;
}
ans[p]=n;
cout<<"! ";
for(int i=0;i<n;i++) cout<<ans[i]<<' ';
puts("");
return 0;
}