构造一个n个数字的排列,使其作为 sigma( gcd( a[i] , a[i+1] ) ) 中第k小的排列。
因为题目给的 k*2 <= n ,所以可以知道只会询问最小到第 n/2 小,易得最多移动一个数字即可得到答案。
假设原始排列为1 2 3 ... n,如果询问最小直接输出排列,否则询问x且x是偶数就把x移动到2*n与2*n-1之间。
如果x是奇数就将x与 2*n-1或者2*n+1交换。因为有可能2*n-1和2*n+1与x-1或者x+1不互质。
//#define test #include<bits/stdc++.h> using namespace std; const int Nmax=1e6+7; typedef long long ll; int a[Nmax]; int n,m; int main() { #ifdef test #endif int t; //freopen("f.in","r",stdin); scanf("%d",&t); for(int cases=1; cases<=t; cases++) { printf("Case #%d:",cases); scanf("%d%d",&n,&m); //printf("n:%d m:%d\n",n,m); for(int i=1; i<=n; i++) a[i]=i; if(m&1) { int l=m-1,r=m+1; if((m!=l && __gcd(2*m-1,l) !=1) || (m != r && __gcd(2*m-1,r)!=1)) swap(a[m],a[2*m+1]); else swap(a[m],a[2*m-1]); } else { a[2*m]=m; for(int i=2*m+1; i<=n+1; i++) a[i]=i-1; for(int i=m; i<=n; i++) a[i]=a[i+1]; } for(int i=1; i<=n; i++) printf(" %d",a[i]); printf("\n"); } return 0; }
原文地址:https://www.cnblogs.com/LMissher/p/9673971.html
时间: 2024-10-26 14:19:50