CF1713C Build Permutation--构造算法确实难
题意:
给定n,从0开始编号,也即(0--n-1),是否有这样的一个排列p(元素为0-n-1,每个元素出现一次),使得pj+i是平方数
解:
由于下标i是固定的,不妨按照递增i来分析
n=7:
0,1,2,3,4,5,6
1,0,2, 6,5,4,3
n=8:
0,1,2,3,4,5,6,7
1,0,7,6,5,4,3,2
n=9:
0,1,2,3,4,5,6,7,8
0,8,7,6,5,4,3,2,1
我们可以发现,对于一定的区间,这个平方数是一样的
对于一样的平方数,我们确定这个区间左右端点,l,r,也就是l+r是一个平方数
那么p[l]=r,p[r]=l.
我们是知道右端点的,最开始r=n-1
对于r,确定x>=n时,最小的平方数x。
codeforces上给了一个结论是:必然能在n-2n之间找到一个平方数x,且为s=pow(floor(sqrt(2*r)),2)
那么左端点即为s-r(l+r==s)
再递归地解决l-1的情况,直到参数<0
#include<iostream> #include<array> #include<cmath> using namespace std; const int maxn=1e5+1e1; array<int,maxn>a; void rec(int r) { if(r<0)return; int s=sqrt(2*r);s*=s; int l=s-r;rec(l-1); for(;l<=r;l++,r--) { a[l]=r;a[r]=l;//l+r==平方数 } } int main() { int t;cin>>t; while(t--) { int n;cin>>n; rec(n-1); for(int i=0;i<n;i++){cout<<a[i]<<" ";}cout<<"\n"; } return 0; }

浙公网安备 33010602011771号