codeforces #309 div1 B
题目啰里啰嗦说了一大堆(耐心读完题目就可以秒题了)
首先我们考虑当前置换的开头的循环节的开头
1、如果是1 1->1形成循环节 问题变成i-1的子问题
2、如果是2 1->2->1形成循环节 问题变成i-2的子问题
3、如果>2 则存在1->x->1形成一个循环节,但在原置换中不连续,所以一定不可能不变
故设长度为i的满足条件的置换个数为f(i)
存在f(i)=f(i-1)+f(i-2)
至于求第K小,逐位确定即可
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=52; typedef long long LL; int n; int a[maxn]; LL f[maxn],k; int main(){ scanf("%d",&n);cin>>k; f[0]=1;f[1]=1; for(int i=2;i<=n;++i)f[i]=f[i-1]+f[i-2]; int pos=1,base=0; while(pos<=n){ if(k>f[n-pos]){ k=k-f[n-pos]; a[pos]=base+2; a[pos+1]=base+1; pos+=2;base+=2; }else{ a[pos]=base+1; pos++;base++; } } for(int i=1;i<=n;++i)printf("%d ",a[i]); return 0; }