1 条题解
-
0
自动搬运
来自洛谷,原作者为

Petit_Souris
鼓励的话语 无论多少次我都会说给你听 | 你在名为弱小的深渊 究竟看见过什么 | 天空中出现了一种罕见的天文现象搬运于
2025-08-24 23:01:25,当前版本为作者最后更新于2024-07-31 15:34:37,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我们考虑用 dp 算出期望最优的策略:设 表示剩下 个人,其中有 个人,他们中已经被确定至少有一个 的期望次数。
当 时,我们枚举 表示查询 个人中的多少人。如果这些人中没有 (概率为 ),会从 转移过来,否则会从 转移过来。
当 时,从 转移过来(已经确定是这个人了)。
当 时,我们枚举 表示查询这 个人中的多少人。如果这些人中没有 (概率为 ),会从 转移过来,否则会从 转移过来。dp 的过程中记录转移的路径。
交互过程只需要根据 dp 得到的路径来构造就行了。时间复杂度为 ,注意实现常数。
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) /// You may use: // The number of students int N; // The probability any given student is positive double P; // This function performs a test on a subset of samples. // Its argument is a vector of Booleans of length N, // where the i-th element is true if the i-th sample should be added to the mix. // It returns true if (and only if) at least one of the samples in the mix is positive. bool test_students(std::vector<bool> mask) { assert(mask.size() == (size_t)N); std::string mask_str(N, ' '); for (int i = 0; i < N; i++) mask_str[i] = mask[i] ? '1' : '0'; printf("Q %s\n", mask_str.c_str()); fflush(stdout); char answer; scanf(" %c", &answer); return answer == 'P'; } /// You should implement: // This function will be called once for each test instance. // It should use test_students to determine which samples are positive. // It must return a vector of Booleans of length N, // where the i-th element is true if and only if the i-th sample is positive. typedef double ld; const ld INF=1e9; ld dp[1009][1009],pb[1009]; int trans[1009][1009]; mt19937 rnd(time(0)); std::vector<bool> find_positive(bool typ) { std::vector<bool> answer(N); if(typ){ rep(i,0,N-1){ vector<bool>msk(N); msk[i]=1; if(test_students(msk))answer[i]=1; } return answer; } vector<int>ord(N); iota(ord.begin(),ord.end(),0); shuffle(ord.begin(),ord.end(),rnd); int i=N,j=0; while(i){ if(j==1){ answer[ord[i-1]]=1; i--,j=0; // if(i)shuffle(ord.begin(),ord.begin()+i-1,rnd); continue; } vector<bool>msk(N); int k=trans[i][j]; per(p,i-1,i-k)msk[ord[p]]=1; bool res=test_students(msk); if(j){ if(!res)i-=k,j-=k; else j=k; } else { if(!res)i-=k; else j=k; } } return answer; } int main() { int T; scanf("%d %lf %d", &N, &P, &T); if(T>1){ pb[0]=1; rep(i,1,N)pb[i]=pb[i-1]*(1-P); rep(i,0,N+1){ rep(j,0,N+1)dp[i][j]=INF; } rep(i,0,N+1)dp[0][i]=0; rep(i,1,N){ dp[i][1]=dp[i-1][0]; rep(j,2,i){ rep(k,1,j){ ld prob=(pb[k]-pb[j])/(1-pb[j]); ld val=dp[i-k][j-k]*prob+dp[i][k]*(1-prob)+1; if(val<dp[i][j])dp[i][j]=val,trans[i][j]=k; } } rep(j,1,i){ ld val=dp[i-j][0]*pb[j]+dp[i][j]*(1-pb[j])+1; if(val<dp[i][0])dp[i][0]=val,trans[i][0]=j; } } } // You may perform any extra initialization here. for (int i = 0; i < T; i++) { std::vector<bool> answer = find_positive(T==1); assert(answer.size() == (size_t)N); std::string answer_str(N, ' '); for (int j = 0; j < N; j++) answer_str[j] = answer[j] ? '1' : '0'; printf("A %s\n", answer_str.c_str()); fflush(stdout); char verdict; scanf(" %c", &verdict); if (verdict == 'W') exit(0); } return 0; }
- 1
信息
- ID
- 10573
- 时间
- 10000ms
- 内存
- 1024MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者