• [loj6797]QC QC


    性质1:若向$i$询问$j$的结果为0,则$i$和$j$中至少有一个机器故障

    性质2:若$i$和$j$相互询问的结果均为1,则$i$和$j$故障状态必然相同

    将$n$台机器分为若干非空等价类(同一个等价类中故障状态相同),将这些等价类分为三组:

    对于第1组等价类,假设有$n_{1}$个,分别记作$S_{i}$,保证$\forall 1\le i\le n_{1},|S_{i}|=2^{k}$(其中$k$为查询轮数)

    对于第2组等价类,假设有$n_{2}$对,分别记作$(X_{i},Y_{i})$,保证$\forall 1\le i\le n_{2},|X_{i}|=|Y_{i}|$且$X_{i}$和$Y_{i}$中至少有一个是故障等价类

    对于第3组等价类,假设有$n_{3}$个,分别记作$T_{i}$,具体性质将在之后叙述

    初始$k=0,n_{1}=n,n_{2}=n_{3}=0$且$S_{i}=\{i\}$,每轮查询如下:

    每一轮操作,$\forall 1\le j\le \lfloor\frac{n_{1}}{2}\rfloor$取$x\in S_{2j-1}$和$y\in S_{2j}$并将$x$和$y$相互询问

    若询问结果均为1,根据性质1将两者合并得到$S_{2j-1}\cup S_{2j}$并作为第1组等价类

    否则(询问结果中存在0),根据性质2将两者合并得到$(S_{2j-1},S_{2j})$并作为第2组等价类

    另外,若$2\not\mid n_{1}$则将$S_{n_{1}}$中的$n_{3}$个元素分别与某个$T_{i}$中的1个元素相互询问(可以证明$n_{3}\le 2^{k}$)

    若查询结果均为1,则将$S_{n_{1}}$与$T_{i}$合并(否则不作处理),并将最终的$S_{n_{1}}$作为第3组等价类

    性质3:$\forall 1\le i\le n_{3},|T_{i}|<2^{k}$且$\forall i\ne j,|T_{i}|\and |T_{j}|=0$($\and$指二进制下的与)

    推论:$n_{3}\le k\le 2^{k}$

    性质4:$\forall 1\le i\le n_{3},T_{i}$中至多一个等价类是非故障等价类

    重复上述过程,直至$n_{1}=0$(三组等价类的性质均可归纳证明,具体过程略)

    注意到第2组等价类中故障机器至少有一半,因此剩余的机器中仍有严格超过一半的非故障机器

    进一步的,结合$n_{1}=0$和性质3、4,不难发现$n_{3}\ge 1$且恰仅有最大的$T_{i}$(必然唯一)是非故障等价类

    另外,对最后一次操作的情况分类讨论:

    1.若操作时$n_{1}=1$,那么这一轮会在第3组等价类加入$|S_{1}|=2^{k-1}$个机器

    若操作前$n_{3}=0$,这一轮并不需要查询,即以$k-1$次查询得到了$2^{k-1}\ge 2^{k-2}+1$个机器的状态

    若操作前$n_{3}\ge 1$,即初始$\sum_{i=1}^{n_{3}}|T_{i}|\ge 1$,进而即以$k$次查询得到了$2^{k-1}+1$个机器的状态

    2.若操作时$n_{1}\ge 2$,则存在$(X_{i},Y_{i})$满足$|X_{i}|=|Y_{i}|=2^{k-1}$,同时结合性质3有$\max |T_{i}|<2^{k}$

    因此$X_{i}$和$Y_{i}$不能同时是故障等价类,用最大的$T_{i}$额外查询一次,即得到了$\ge 2^{k-1}+1$个故障机器和$\ge 2^{k-1}$个非故障机器

    换言之,即以$k+1$次查询得到了$\ge 2^{k}+1$个机器的状态

    总得来说,设查询了$k_{0}$轮,会得到$\ge 2^{k_{0}}+1$个机器的状态和$n_{2}$对第2组等价类

    设当前有$x$个非故障机器和$y$个故障机器,对其分类讨论:

    1.若$x-y\le 2$,那么每一对第2组等价类均不能同时是故障等价类,因此可以一轮可以查询$x$对第2组等价类

    2.若$x-y>2$,那么对每一组等价类查询,一轮可以查询$\lfloor\frac{x}{2}\rfloor$对第2组等价类

    查询轮数的级别是$o(\log n)$的,并且通过具体计算必然查询必然不超过10轮

    最终,总复杂度为$o(tn\log n)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 105
      4 int t,n,k,n1,n2,n3,nn1,nn3,v[N];
      5 char s[N],ans[N];
      6 vector<int>X0,Y0,S[N],X[N],Y[N],T[N],SS[N],TT[N];
      7 void query(){
      8     printf("test ");
      9     for(int i=1;i<=n;i++)printf("%d ",v[i]);
     10     printf("\n");
     11     fflush(stdout);
     12     scanf("%s",s+1);
     13 }
     14 int main(){
     15     scanf("%d",&t);
     16     while (t--){
     17         scanf("%d",&n);
     18         k=0,n1=n,n2=n3=0;
     19         for(int i=1;i<=n1;i++)S[i].clear(),S[i].push_back(i);
     20         bool flag=0;
     21         while (n1){
     22             if (n1==1){
     23                 flag=1;
     24                 if (!n3){
     25                     n1=0,T[++n3]=S[1];
     26                     break;
     27                 }
     28             }
     29             k++,nn1=nn3=0;
     30             memset(v,0,sizeof(v));
     31             for(int i=2;i<=n1;i+=2){
     32                 v[S[i-1][0]]=S[i][0];
     33                 v[S[i][0]]=S[i-1][0];
     34             }
     35             if (n1&1){
     36                 for(int i=1;i<=n3;i++){
     37                     v[S[n1][i-1]]=T[i][0];
     38                     v[T[i][0]]=S[n1][i-1];
     39                 }
     40             }
     41             query();
     42             for(int i=2;i<=n1;i+=2){
     43                 if ((s[S[i-1][0]]=='0')||(s[S[i][0]]=='0'))X[++n2]=S[i-1],Y[n2]=S[i];
     44                 else{
     45                     SS[++nn1]=S[i-1];
     46                     for(int j=0;j<S[i].size();j++)SS[nn1].push_back(S[i][j]);
     47                 }
     48             }
     49             if (n1&1){
     50                 for(int i=1;i<=n3;i++)
     51                     if ((s[S[n1][i-1]]=='0')||(s[T[i][0]]=='0'))TT[++nn3]=T[i];
     52                     else{
     53                         for(int j=0;j<T[i].size();j++)S[n1].push_back(T[i][j]);
     54                     }
     55                 n3=nn3,TT[++n3]=S[n1];
     56                 for(int i=1;i<=n3;i++)T[i]=TT[i];
     57             }
     58             n1=nn1;
     59             for(int i=1;i<=n1;i++)S[i]=SS[i];
     60         }
     61         X0=T[n3],Y0.clear();
     62         for(int i=1;i<n3;i++)
     63             for(int j=0;j<T[i].size();j++)Y0.push_back(T[i][j]);
     64         if (!flag){
     65             memset(v,0,sizeof(v));
     66             v[T[n3][0]]=X[n2][0],query();
     67             if (s[T[n3][0]]=='0')swap(X[n2],Y[n2]);
     68             for(int i=0;i<X[n2].size();i++)X0.push_back(X[n2][i]);
     69             for(int i=0;i<Y[n2].size();i++)Y0.push_back(Y[n2][i]);
     70             n2--;
     71         }
     72         while (X0.size()+Y0.size()<n){
     73             int sx=X0.size();
     74             memset(v,0,sizeof(v));
     75             if (X0.size()-Y0.size()<=2){
     76                 for(int i=0;i<X0.size();i++)
     77                     if (i<n2)v[X0[i]]=X[n2-i][0];
     78                 query();
     79                 for(int i=0;i<sx;i++)
     80                     if (n2){
     81                         if (s[X0[i]]=='0')swap(X[n2],Y[n2]);
     82                         for(int j=0;j<X[n2].size();j++)X0.push_back(X[n2][j]);
     83                         for(int j=0;j<Y[n2].size();j++)Y0.push_back(Y[n2][j]);
     84                         n2--;
     85                     }
     86             }
     87             else{
     88                 for(int i=1;i<X0.size();i+=2)
     89                     if ((i>>1)<n2){
     90                         v[X0[i-1]]=X[n2-(i>>1)][0];
     91                         v[X0[i]]=Y[n2-(i>>1)][0];
     92                     }
     93                 query();
     94                 for(int i=1;i<sx;i+=2)
     95                     if (n2){
     96                         if (s[X0[i-1]]=='1'){
     97                             for(int j=0;j<X[n2].size();j++)X0.push_back(X[n2][j]);
     98                         }
     99                         else{
    100                             for(int j=0;j<X[n2].size();j++)Y0.push_back(X[n2][j]);
    101                         }
    102                         if (s[X0[i]]=='1'){
    103                             for(int j=0;j<Y[n2].size();j++)X0.push_back(Y[n2][j]);
    104                         }
    105                         else{
    106                             for(int j=0;j<Y[n2].size();j++)Y0.push_back(Y[n2][j]);
    107                         }
    108                         n2--;
    109                     }
    110             }
    111         }
    112         for(int i=1;i<=n;i++)ans[i]='0';
    113         for(int i=0;i<X0.size();i++)ans[X0[i]]='1';
    114         printf("answer ");
    115         for(int i=1;i<=n;i++)putchar(ans[i]);
    116         putchar('\n');
    117         fflush(stdout);
    118     }
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    工作也是一样,认真对待,你是在为自己工作
    程序员学习能力提升三要素(转载)
    该读些啥书
    每个程序员都应读的书
    微博时光机定时发送微博
    WordPress快速建站
    Tweenlite的用法
    Away3D粒子系统中文快速上手指南
    操盘手 李彪 照片[转]
    URLClassLoader加载class到当前线程类加载器【zt】
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15920719.html
Copyright © 2020-2023  润新知