专栏文章
CF1583D
CF1583D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miny3n1n
- 此快照首次捕获于
- 2025/12/02 10:14 3 个月前
- 此快照最后确认于
- 2025/12/02 10:14 3 个月前
题解
先求出 的值。
具体地,先从 到 枚举一个数 ,询问 ,此时若返回 ,则 已经确定,即 ;若返回其他的 ,则标记 ,求出 后再将所有被标记的 处理为正确的值。
特殊地,若 ,返回的 均不为 ,则 ,然后此时所有 已经被标记,于是就可以在 步内求出序列。
为什么这样求
根据排列性质,如果 ,则这个值必定在排列中出现过,且整个排列没有重复的元素。因此可以直接询问 。
但是因为询问的数组必须满足所有元素在 ,所以将整个数组往上 后询问。
这样处理之后,发现所有大于 的位置都会被标记,所以只需要求小于 的位置了。
类似地,对于一个数 的位置(),可以询问数组 ,返回值 即为 的位置。
为什么这样构造
可以发现构造的数组 满足除下标 外的所有值都和 相差 。所以这个数组其实等价于 。
这样,就可以在 步或者 步内求出 。
代码
CPP#include<bits/stdc++.h>
using namespace std;
int n;
int p[105];
int main() {
scanf("%d",&n);
int pd=1;
p[n]=n+1;
while(pd) {
p[n]--;
if(p[n]==1) break;
printf("? ");
for(int i=1;i<n;i++) printf("1 ");
printf("%d\n",n-p[n]+2);
fflush(stdout);
scanf("%d",&pd);
p[pd]=n-p[n]+1;
}
for(int i=1;i<n;i++) if(p[i]) p[i]+=p[n];
pd=0;
for(int i=1;i<p[n];i++) {
printf("? ");
for(int j=1;j<n;j++) printf("%d ",p[n]-i+1);
puts("1");
fflush(stdout);
scanf("%d",&pd);
p[pd]=i;
}
printf("! ");
for(int i=1;i<=n;i++) printf("%d ",p[i]);
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...