Cantor expansion of ac number theory

For the full permutation of n numbers, there are n! How to find the order of a certain sequence in the whole arrangement (from small to large)?

Take the full permutation of 9 as an example: 842697513 is the first number in the full permutation of 1-9? (For high school math permutation and combination problems, you only need to do it without repetition )

First of all, if the first position is 8, then all permutations with the first position of 1-7 are smaller than it, a total of 7*8! indivual.

In the case that the first digit is 8, and then the second digit is 4, then the whole permutation of the second digit 1-3 is smaller than it, a total of 1*3*7! indivual.

In the case where the first digit is 8 and the second digit is 4, then the whole permutation of the third digit 1 is smaller than it, a total of 1*1*6! indivual.

In the case where the first digit is 8, the second digit is 4, and the third digit is 2, then the whole arrangement of the fourth digit 1-5 is smaller than it. OK, the possible value of the fourth digit can only be (1,3,5), a total of 1*1*1*3*5!

In the case where the first digit is 8, the second digit is 4, the third digit is 2, and the fourth digit is 6, then the entire permutation of the fifth digit 1-8 is smaller than it. Here, since the second digit is 4. The third digit is 2, and the fourth digit is 6. It has been determined that the possible value of the fifth digit can only be (1,3,5,7), a total of 1*1*1*1*4*4!

......

For the possible value of the i-th bit, the number of the first i-bit has been determined, and each number can only appear once in the whole arrangement. It is only necessary to compare how many numbers after the i-bit are smaller than the i-bit number. Know the possible values ​​of the ith bit.


Summarizing the above method, calculate the full permutation of 1-n


a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!


Cantor expansion

Cantor expansion

Cantor expansion is a special hash function, its scope of use is to compress and store the state of the permutation of n numbers, for example, to judge the full permutation of 9. It is not necessary

Open an array of 10^9, and the memory does not allow to open such a large array. In this regard, someone proposed an optimization, that is, for a permutation number of n, it is not necessary to open to 10^n, because in a permutation each The number only appears once, so as long as the first n-1 bits are determined, the first N bits are determined.

But the above idea is still not feasible, because N can be very large, such as 15, so the Cantor expansion is introduced: it is only necessary to determine the smallest number of this permutation in the total permutation situation.

For example: I want to know that 321 is the largest number in the arrangement of {1,2,3}. Consider that the first digit is 3. When the number in the first digit is less than 3, the number of the arrangement is less than 321, such as 123 213 The number less than 3 has 1, 2, so there is 2*2! Look at the number less than 2, which is less than the second digit, only one is 1, so there is 1*1!=1, so it is less than 321 {1,2,3} There are 2*2!+1*1!=5 permutations so 321 is the sixth largest number. 2*2!+1*1! is the Cantor expansion.


I'm number one

Time Limit: 1000  ms | Memory Limit: 65535  KB
Difficulty: 3
describe

Now there are 12 characters "abcdefghijkl", arrange all their permutations in lexicographical order, and give any permutation, say which permutation is the smallest among all the permutations?

enter
The first line has an integer n (0<n<=10000);
then there are n lines, each line is a permutation;
output
Output an integer m, occupying one line, m indicates the number of the arrangement;
sample input
3
abcdefghijkl
hgebkflacdji
gfkedhjblcia
Sample output
1
302715242
260726926

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int power[13];
void db()
{
    power[0]=power[1]=1;
    for(int i=1; i<=12; i++)
        power[i]=power[i-1]*i;
}
intmain()
{
    int ncase;
    cin>>ncase;
    db();
    getchar();
    while(ncase--)
    {
        char c[30];
        cin.getline(c,30);
        int l=strlen(c);
        long long sum=0;
        for(int i=0; i<l; i++)
        {
            int tt=0;
            for(int j=l-1; j>i; j--)//从后向前扫描,寻找比自己小的,就是比c[i]位置小的几种情况
                if(c[j]<c[i])
                {
                    tt++;
                }
                //然后在乘以后面所有位数的全排列
                sum+=tt*power[l-i-1];
        }
        cout<<sum+1<<endl;
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326483800&siteId=291194637