hdu2062

来源:互联网 发布:java培训需要多少钱 编辑:程序博客网 时间:2024/06/13 07:57
/*
分析:
    不是太难额,竟然用了1个多小时,反思……


    思路:
        假如有n个数,那么第i个数后面的数可以构成种类数
s=A(1,n-i)+A(2,n-i)……+A(n-i,n-i);
        明白这点后,从第一位开始找,设x为从小到大第几个
    还没有被占用的数,主循环为for(i=1;i<=n;i++),找到x
    满足:第i位用从小到大第x个数的话,其所代表总序列数
    一定大于m;而对于x-1大的数,不成立。
        那么第i位取从小到大第x-1数。


    具体的看代码吧,注意要用64位的。


                                                    2012-07-09
*/








#include"stdio.h"__int64 base[22];__int64 fac(__int64 n){__int64 z=1;__int64 i;for(i=2;i<=n;i++)z*=i;return z;}__int64 rec(__int64 x,__int64 t,__int64 m){while(x*t<m)x++;return x;}int main(){__int64 ans[22],k;__int64 n,m;__int64 t;__int64 hash[22];__int64 i,l,j;base[0]=1;for(i=1;i<=20;i++){base[i]=0;for(l=1;l<=i;l++)base[i]+=fac(i)/fac(i-l);}while(scanf("%I64d%I64d",&n,&m)!=-1){for(i=0;i<22;i++)hash[i]=1;k=0;for(i=0;i<n;i++){if(m==0)break;k++;t=rec(1,base[n-i-1]+1,m);for(l=1,j=0;l<=n;l++){if(hash[l]){j++;if(j==t){ans[i]=l;hash[l]=0;break;}}}m-=(t-1)*(base[n-i-1]+1);m--;}for(i=0;i<k-1;i++)printf("%I64d ",ans[i]);printf("%I64d\n",ans[i]);}return 0;}


原创粉丝点击