杭电1027

很简单的一道题,初中时常做,其实就是求第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;

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值