CF1469D

· · 题解

题面

一个长为 n 数组 a,初始满足 a_{i}=i

可以做不超过 n+5 次操作:每次选定满足 x \neq y 的两个下标 x,y,令 a_{x}=\lceil \frac{a_{x}}{a_{y}} \rceil

问是否可以将 a 数组变为含 n-1112 的数组。

题解

不知道,只会暴力。

然后要处理这个 $n$,在 $[2,n-1]$ 里找一个数 $x$,对 $n$ 和 $x$ 做操作,每次大除以小直到一个数为 $1$,特判另一个数是否为 $2$,如果为 $2$ 那么这个方案是合法的。 上面这个可以直接模拟。 然后从 $2$ 到 $n-1$ 暴力枚举找到做操作次数最小的 $x$。在 $[1,n]$ 中所有数,除了 $1$,$x$ 和 $n$ 全都直接除以 $n$,然后 $x$ 和 $n$ 照上面那个模拟互相除。 时间复杂度 $O(n \log n)$。 ## 代码 ```cpp #include<bits/stdc++.h> using namespace std; int _; int n; int main() { scanf("%d",&_); while(_--) { scanf("%d",&n); if(n<3) {puts("0");continue;} int ans=30000,s=0; for(int i=2;i<n;i++) { int x1=i,x2=n,cnt=0; while(x1>1&&x2>1) { if(x2>x1) x2=(x2+x1-1)/x1,cnt++; else x1=(x1+x2-1)/x2,cnt++; } if(cnt<ans&&(x1==2||x2==2)) ans=cnt,s=i; } printf("%d\n",n-3+ans); for(int i=2;i<n;i++) if(i!=s) printf("%d %d\n",i,n); // for(int i=n;i>=3;i--) printf("%d %d\n",i,i/2+1); int x1=s,x2=n; while(x1>1&&x2>1) { if(x2>x1) x2=(x2+x1-1)/x1,printf("%d %d\n",n,s); else x1=(x1+x2-1)/x2,printf("%d %d\n",s,n); } } return 0; } ```