Ignatius and the Princess II
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5774 Accepted Submission(s): 3398
"Now I will show you the first problem." feng5166 says, "Given a sequence of number 1 to N, we define that 1,2,3...N-1,N is the smallest sequence among all the sequence which can be composed with number 1 to N(each number can be and should be use only once in this problem). So it's easy to see the second smallest sequence is 1,2,3...N,N-1. Now I will give you two numbers, N and M. You should tell me the Mth smallest sequence which is composed with number 1 to N. It's easy, isn't is? Hahahahaha......"
Can you help Ignatius to solve this problem?
題意:給定兩個整數N、M。將1~N排列組合,按字典序從小到大排列,求出排在第M個的排列。
雖然N的範圍很大,到1000,1000的階乘很嚇人呀,但是M的範圍只到10000,而8的階乘就已經超過10000了,所以無論N多大,我們最多隻要考慮後八位的排列組合問題。
先判斷M與階乘數的大小,確定要考慮後幾位的排列組合。假設是考慮後x位的排列組合,先將1~N-x-1順序輸出。然後處理剩餘的數:用M對(x-1)的階乘求商a,取餘賦值給M自身。若M爲0,則倒數第x位取第a大的數,剩餘幾位倒序排列;若M不爲0,則倒數第x位取第(a+1)大的數,再用同樣方法考慮後(x-1)位數,以此類推。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int biao[9]= {1,1,2,6,24,120,720,5040,40320};
int main()
{
int n,m,x,a,cnt;
int rest[2],store[9];
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i = 0; i < 9; i++)
store[i] = 1005;
for(int i = 1; i <= 8; i++)
if(biao[i] > m)
{
x = i;
break;
}
for(int i = 1; i <= n - x; i++)
printf("%d ",i);
for(int i = 1; i <= x; i++)
store[i] = n - x + i;
for(int i = x - 1; i >= 1; i--)
{
sort(store, store + 9);
a = m / biao[i];
m %= biao[i];
if(m)
{
printf("%d ",store[a]);
store[a] = 1005;
}
else
{
printf("%d ",store[a - 1]);
store[a - 1] = 1005;
break;
}
}
sort(store, store + 9);
for(int i = 8; i > 0; i--)
if(store[i] != 1005)
printf("%d ",store[i]);
printf("%d\n",store[0]);
}
}