蛮不好想的,但实现极端容易。
这道题第一步得读明白题,才能找到规律。首先每个循环得是标准循环,而且每个循环所有值之间必须挨着(不然将循环重新排序后顺序就会改变)
好,读明白题后,根据筛选原理,打个表,找规律。。(打表程序顶仨题解)
我把5的贴上(太大的没敢贴)
1 2 3 4 5
1 2 3 5 4
1 2 4 3 5
1 3 2 4 5
1 3 2 5 4
2 1 3 4 5
2 1 3 5 4
2 1 4 3 5
按此方式分开,会很想fibonaci。0位的是不改变的,之后动第一位,动第二位,动第三位,动第三位+第一位。从这里开始,就有从新开始开始了一个新的fibo循环,正好符合fibo的特性。
因此,就用这种方法一直减k,并标记那几位被调转了位置。这里还要解释一下。n-1位与n位换后就被固定住,不再换了,打下标记即可。说白了就是fibo减到第几位,k比他小了,那么当前位就是要换的位。
程序
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #define ll long long using namespace std; int n,a[100],v[100]; ll k,f[100]; int main() { scanf("%d%lld",&n,&k); f[0]=f[1]=f[2]=1; for(int i=3;i<=n;i++)f[i]=f[i-1]+f[i-2]; for(int i=1;i<=n;i++)a[i]=i; while(k>1) { int i=0; while(k>f[i])k-=f[i],i++; v[n-i+1]=v[n-i]=1; } for(int i=1;i<n;i++) if(v[i]&&v[i+1]) v[i]=v[i+1]=0,swap(a[i],a[i+1]); for(int i=1;i<=n;i++)printf("%d ",a[i]);//别笑就二十七行。。。 }然后,,打表的程序
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<string> #include<cmath> using namespace std; int n; long long k; struct no{ int a[80]; long long js; bool friend operator > (no a,no b) { return a.js>b.js; } }; int px(int x,int y) { return x>y; } struct nod{ int a[80]; int zz; bool friend operator > (nod a,nod b) { return a.a[1]>b.a[1]; } }; priority_queue<no,vector<no>,greater<no > > q1; bool us[80]; int a[80]; void dfs(int jj){ if(jj==n) { priority_queue<nod,vector<nod>, greater<nod > > q2; bool fw[80]; memset(fw,0,sizeof(fw)); for(int i=1;i<=n;i++) { if(!fw[i]) { int be=i; bool yxx=1; nod x; x.zz=0; memset(x.a,0,sizeof(x.a)); for(int j=i;;j=a[j]) { if(fw[j]) break; fw[j]=1; x.zz++; x.a[x.zz]=j; } sort(x.a+1,x.a+x.zz+1,px); q2.push(x); } } int jss=1; bool yxx=1; while(!q2.empty()) { nod x=q2.top(); q2.pop(); //jss++; for(int i=1;i<=x.zz;i++) { if(a[jss]!=x.a[i]) { yxx=0; break; } jss++; } } if(!yxx)return; long long sum=0; for(int i=1;i<=n;i++) { sum=sum*2+a[i]; } no st; st.js=sum; memcpy(st.a,a,sizeof(a)); q1.push(st); return; } bool uu[80]; memcpy(uu,us,sizeof(us)); int aa[80]; memcpy(aa,a,sizeof(aa)); int jjj=jj; bool yx=1; for(int i=1;i<=n;i++) { if(!us[i]) { yx=0; us[i]=1; jj++; a[jj]=i; dfs(jj); memcpy(us,uu,sizeof(uu)); memcpy(a,aa,sizeof(aa)); jj=jjj; } } } int main(){ freopen("fuck5.out","w",stdout); scanf("%d%lld",&n,&k); dfs(0); int js=0; while(!q1.empty()) { js++; for(int i=1;i<=n;i++) cout<<q1.top().a[i]<<' '; cout<<endl; q1.pop(); } return 0;//比题目多了一百行。。。 }