很简单的一道题,初中时常做,其实就是求第M小的序列
把一些方法放到函数里程序简单一点,但是变量还是显得很乱。
再有就是逻辑是在写的过程中想清楚的,所以错了很多次,这样很不好,还是应该想好再写。
对于这个程序,有两步较重要,就是在交换后,必须保证K后序列为有序且为从小到大。
最后呢,终于对了,还是挺开心!
#include<iostream>
using namespace std;
void swap(int a[], int x, int y);
void sort(int a[], int x, int y);//已知,x到y除y均为从小到大,且y为最小,将其排列为从小到大。
int main()
{
int fac[10];//计算阶乘小于10000的数字的阶乘值
fac[1] = 1;
for (int i = 2; i <= 9; i++)
fac[i] = fac[i - 1] * i;
int N, M;
while (cin >> N >> M)
{
int num[1001] ;//将1000个数字存放于数组中以利于交换
for (int i = 1; i < 1001; i++)
num[i] = i;
//例如1234 M=6=3!只需234逆序即可,M=7=3!+1那么将1变为2,后面仍为正序即为所求
//M=1时,既为当下那个数,不用进行任何操作,故M=7,经过一次循环得到第七个数然后不再进行任何操作,
//M=9,第一次循环得到第7个序列,然后M=2=2!,第二次循环i=2,将最后两个数逆序即可
//M=9,第一次循环得到第7个序列后,M=3,此时和初始状态去求第3个序列等价(以第7个为基础,去寻求第3个序列)
while (M)
{
int j;
for (j = 1; fac[j] <= M; j++);
j = j - 1;//j!<=M<i!
int k = N - j;//k以后数字变化
int t = M / fac[j];
M = M%fac[j];
if (M)//经过循环变为第t*fac[j]+1个序列//且保证k+1为以后数字为升序
{
swap(num, k, k + t);
sort(num, k+1, k + t);
}
else//如果M就是j的阶乘的整数倍,那么只需要调整第k位的数字,然后将k位以后数字逆序即可
{
swap(num, k, k + t - 1);
sort(num, k+1, k + t - 1);
for (int m = k + 1, n = N; m < n; m++, n--)
swap(num, m, n);
}
}
//输出
for (int i = 1; i <= N; i++)
{
cout << num[i];
if (i != N)
cout << ' ';
}
cout << endl;
}
return 0;
}
void swap(int a[], int x, int y)
{
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
void sort(int a[], int x, int y)
{
if (y > x) {
int temp = a[x];
swap(a, x, y);
for (int i = y; i > x + 1; i--)
{
a[i] = a[i - 1];
}
a[x + 1] = temp;
}
}