[关闭]
@xiaoziyao 2021-08-18T06:30:49.000000Z 字数 1632 阅读 792

P7824 「RdOI R3」毒水 解题报告

解题报告


P7824 「RdOI R3」毒水解题报告:

更好的阅读体验

题意

瓶水,其中一瓶有毒,你可以检测若干次,每次选择若干瓶水,检测其中是否有毒水,但有且仅有一次检测结果会反过来,你需要在 次检测内找出毒水。注意,结果不是实时得到,当你询问结束后才能一次性得到所有结果。

分析

交互杀我!!!

:很容易把每一瓶水检验三次,只要有两次检验出来就一定是毒水。

:考虑没有那次反过来的检测如何求,我们可以直接检测每个二进制位是否有毒水,然后拼起来就好了,如果有那次反过来的检测,检测三次就可以避免。

:检验三次消耗过大,考虑快速检验二级制位。

我们用 次检测对二进制位的检测再次二进制拆分,然后再用 次检测作为新加入的检测的异或。

很容易发现如果反转不在新加入的 个检测,那么这 个检测的死亡数为偶数。于是如果其为偶数,我们可以直接找到反转在前 个检测中的位置,否则前 个检测可以直接算。

检测次数 ,符合要求。

代码

  1. #include<stdio.h>
  2. #include<bitset>
  3. #include<math.h>
  4. using namespace std;
  5. const int maxn=1005,maxk=15;
  6. int n,k,lg,lglg;
  7. int v[maxk];
  8. bitset<maxn>ans,b[maxk];
  9. int main(){
  10. scanf("%d%d",&n,&k);
  11. if(n==1&&k==0){
  12. puts("2"),fflush(stdout);
  13. puts("1"),fflush(stdout);
  14. return 0;
  15. }
  16. lg=log2(n-1)+1,lglg=log2(lg-1)+1;
  17. for(int i=0;i<lg;i++){
  18. for(int j=0;j<n;j++)
  19. if((j>>i)&1)
  20. b[i][j]=1;
  21. printf("1 %d ",b[i].count());
  22. for(int j=0;j<n;j++)
  23. if(b[i][j])
  24. printf("%d ",j+1);
  25. puts("");
  26. }
  27. for(int i=0;i<lglg;i++){
  28. for(int j=0;j<lg;j++)
  29. if((j>>i)&1)
  30. b[lg+i]^=b[j];
  31. printf("1 %d ",b[lg+i].count());
  32. for(int j=0;j<n;j++)
  33. if(b[lg+i][j])
  34. printf("%d ",j+1);
  35. puts("");
  36. }
  37. for(int i=0;i<lglg;i++)
  38. b[lg+lglg]^=b[lg+i];
  39. printf("1 %d ",b[lg+lglg].count());
  40. for(int i=0;i<n;i++)
  41. if(b[lg+lglg][i])
  42. printf("%d ",i+1);
  43. puts("\n2"),fflush(stdout);
  44. for(int i=0;i<=lg+lglg;i++)
  45. scanf("%d",&v[i]);
  46. int ok=0;
  47. for(int i=0;i<=lglg;i++)
  48. ok^=(v[lg+i]^1);
  49. if(ok==0){
  50. int pos=0;
  51. for(int i=0;i<lglg;i++){
  52. int ook=(v[lg+i]^1);
  53. for(int j=0;j<lg;j++)
  54. if((j>>i)&1)
  55. ook^=(v[j]^1);
  56. pos+=(ook<<i);
  57. }
  58. v[pos]^=1;
  59. }
  60. ans.set();
  61. for(int i=0;i<lg;i++)
  62. if(v[i]==0)
  63. ans&=b[i];
  64. for(int i=0;i<n;i++)
  65. if(ans[i]){
  66. printf("%d\n",i+1),fflush(stdout);
  67. break;
  68. }
  69. return 0;
  70. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注