[cf1428H]Rotary Laser Lock

For convenience, the number of the initial left end point of the 0 interval is 0, and the other positions are $[1,nm) clockwise$

Consider rotating the 0 interval clockwise and record $s_{i} $is the answer when the left end point of the 0 interval is rotated to $I $(agreed $s {I + n} = s {I} $)

Nature 1: if $s_{i}-s_{i-1}=1 $and $s_{i+1}-s_{i}\ne 1 $(where $0 \ le I < nm $), there is an interval with $I $as the left endpoint

Record $a_{i} $is whether there is an interval except 0, including position $I $(existence is 1). It is not difficult to get $s_{i}-s_{i-1}=a_{i+m-1}-a_{i-1}$

Substitution condition, by $s_{i}-s_{i-1}=1 $$a_{i+m-1}=1 $and $a_{i-1}=0 $, and $a_{i+m}\ne 1 $or $a_{i}\ne 0$

For the discussion of the latter, take the first case as an example, that is $a_{i+m-1}=1 $and $a_{i+m}\ne 1(=0) $, obviously

At the same time, obviously $s_{i} There must be such $I $in $, which is recorded as $I $and rotates the other intervals counterclockwise once

Property 2: $s'_{i} $is $s after counter clockwise rotation of interval $j $_ {i} $, then $j $takes $I $as the left endpoint if and only if $s'_{I}-s'_{I-1}\ne 1$

If $j $has $I $as its left endpoint, notice that this causes $a_{I-1} $becomes 1, which is $s'_{I}-s'_{I-1}\ne 1$

On the other hand, it needs to affect $a_{I-1} $or $a_{I+m-1} $, and the former is initially 0 and the latter is initially 1, so only $I $can be used as the left endpoint

 

To sum up, consider repeating the following process until you get the answer——

1. Find $I $and move the 0th interval to the position with $I $as the left endpoint

2. Enumerate all sections whose positions are not determined. You can determine whether it takes $I $as the left endpoint and restore it through 4 moves

In addition, it can determine $s at the same time through a reasonable operation sequence_ {i}-s_ Whether {I-1} $is 1 (if it is not 1, there is no interval with $I $as the left endpoint)

3. For the interval where the left end point is on $I $, move $m+1 $counterclockwise again (it is required not to cover $I-1 $)

(in fact, this process is to keep finding the beginning of consecutive segments)

Further, considering the operation times required by the above process, consider each step separately:

1. For the first step, it is not difficult to find that after finding it for the first time, turn it at most once, totaling $2nm+2(n-1) $times

2. For the second step, there are $n-1 $rounds, and the $I $round has at most $n-i $intervals, totaling $4\sum_{i=1}^{n-1}(n-i)$

3. For the third step, if the last time in the second step is not restored, only $M-1 $times are actually generated each time, totaling $(n-1)(m-1) $times

After summation, $2n^{2}+3nm-n-m-1=25879 $times in total, unable to pass

 

For the extension of property 2, rotate multiple intervals each time and let them form a set $S $, then there is an interval with $I $as the left end point in $S $if and only if $s'_{I}-s'_{I-1}=1$

Continue to score two points with this method, that is, the number of moves in the 0 interval becomes $2\log n $, and the number of moves decreases to $2\sum_{i=1}^{n-1}(n-i)+2(n-1)\log n$

At the same time, due to continuous dichotomy, it is determined that the interval that does not take $I $as the left endpoint does not need to be restored (it may be skipped after moving from $I+1 $to $I $)

In addition, at this time, $4(n-1) $inspections will be added in the second step, and $m+1 $inspections will be generated in the third step

To sum up, the times of the last two steps are $\ sum respectively_ {I = 1} ^ {n-1} (n-i) + 2 (n-1) (\ log n + 2) $and $(n-1)(m+1)$

After summation, $\ frac {n ^ {2} {2} + 3nm + 2n \ log n + \ frac {11n} {2}-2 \ log n-m-7 = 13107 $times in total, which can be passed

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 105
 4 vector<int>v;
 5 int n,m,L,now,ans[N];
 6 void move(int k,int p){
 7     printf("? %d %d\n",k,p);
 8     fflush(stdout);
 9     scanf("%d",&now);
10 }
11 int main(){
12     scanf("%d%d",&n,&m),L=n*m;
13     for(int i=1;i<n;i++)ans[i]=-1;
14     move(0,1);
15     int lst=now,flag=0;
16     for(int i=0;i<(L<<1);i++){
17         move(0,1);
18         if (ans[0]==n-1)continue;
19         if (lst+1==now)flag=1;
20         else{
21             if (flag){
22                 move(0,-1);
23                 while (1){
24                     if (ans[0]==n-1)break;
25                     move(0,-1),lst=now,move(0,1);
26                     if (lst+1!=now)break;
27                     lst=now,move(0,1);
28                     if (lst+1==now){
29                         move(0,-1);
30                         break;
31                     }
32                     move(0,-1),v.clear();
33                     for(int j=1;j<n;j++)
34                         if (ans[j]<0)v.push_back(j);
35                     int l=0,r=(int)v.size()-1,flag=0;
36                     while (l<r){
37                         int mid=(l+r>>1);
38                         if (!flag){
39                             for(int j=l;j<=mid;j++)move(v[j],-1);
40                         } 
41                         else{
42                             for(int j=mid+1;j<=r;j++)move(v[j],1);
43                         }
44                         move(0,-1),lst=now,move(0,1);
45                         if (lst+1==now)l=mid+1,flag=0;
46                         else r=mid,flag=1;
47                     }
48                     for(int j=0;j<=m-flag;j++)move(v[l],-1);
49                     ans[0]++,ans[v[l]]=(i+L-m-1)%L;
50                 }
51                 lst=now,move(0,1);
52             }
53             flag=(lst+1==now);
54         }
55         lst=now;
56     }
57     printf("! ");
58     for(int i=1;i<n;i++)printf("%d ",ans[i]);
59     fflush(stdout);
60     return 0;
61 }

 

Keywords: CodeForces

Added by alevsky on Sun, 16 Jan 2022 17:59:00 +0200