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 }