Cantor expansion

(1) Cantor expansion: Let X be the number of a permutation in all permutations:

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

Where a[i] is the number (starting from 0) of the elements that are not currently present, which is the legendary Cantor expansion

e.g. Blue Bridge Cup

Topic description:

An archaeological activity in Galaxy X has uncovered traces of prehistoric intelligence.
These are some symbols used for counting. After analysis, the counting rules are as follows:
(For convenience, we replace these strange symbols with a~q)
abcdefghijklmnopq means 0
abcdefghijklmnoqp means 1
abcdefghijklmnpoq means 2
abcdefghijklmnpqo means 3
abcdefghijklmnqop means 4
abcdefghijklmnqpo means 5
abcdefghijklmonpq means 6
abcdefghijklmonqp means 7
.....
The symbol carved on a stone is:
bckfqlajhemgiodnp
Could you please calculate what number it represents?


#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
intmain()
{
    map<char,int>my;
    for(int i=0;i<=26;i++){
        my['a'+i]=i+1;
    }
    char str1[18]={"bckfqlajhemgiodnp"};
    ll a[18],b[18];
    for(int i=0;i<17;i++){
        a[i]=my[str1[i]];
    }
    ll p[18]={1};
    for(ll i=1;i<=18;i++){
        p[i]=p[i-1]*i;
    }
    int force[18]={0};
    ll ans=0;
    for(int i=0;i<17;i++){
        vis[a[i]]=1;
        int cnt=0;
        for(int j=a[i];j>0;j--){
            if(vis[j]==0){
                cnt++;
            }
        }
        ans=ans+(p[17-(i+1)]*cnt);
    }
    printf("%lld\n",ans);
    return 0;
}

Problem Description 
Define a number as a lucky number if and only if all its digits are 4 or 7.
For example, 47, 744, and 4 are all lucky numbers while 5, 17, and 467 are not.
Now want to know how many lucky numbers are in the kth smallest permutation of 1...n (permutation, https://en.wikipedia.org/wiki/Permutation), where the sequence numbers are also lucky numbers.
Input description:
two integers n, k in the first line.
1 <= n, k <= 1000,000,000
Output description:
A number representing the answer.
If n does not have k permutations, output -1.
Example 1
input
7 4
output

1


Solution: k<=1000000000, but 13! >k, so except for the last 13 digits, all the previous digits are fixed, how many lucky numbers can be directly counted, and the last 13 digits are left, because considering the kth is the smallest, we can use the inverse Cantor expansion Now, the maximum complexity is 13*13.

Inverse Cantor expansion: As the name suggests, it is the reverse Cantor expansion. If you ask you to find the k-th smallest permutation, let k/(n-1)!, find a[n], and then k%(n-1 )!, an analogy to find the value at n positions, this process we can understand through forward expansion, carefully observe the formula, we will find that a[n]*(n-1)! must be higher than the sum of all the following items It must be larger, so every time you divide the corresponding coefficient of a[i], the result is that there are several numbers smaller than this number behind this digit, so you can violently find out the number of digits that should be filled in this item, go here It should be almost the same. . .


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 5e9
ll n,k,ans,vis[20],a[20];
ll num[20],q[1000005],pre[20]={1};
void dfs(ll x,ll y)
{
	if(x>y) return;
	if(x) ans++;
	dfs(x*10+4,y);
	dfs(x*10+7,y);
}
int jud(ll x)
{
	while(x)
	{
		int tmp=x%10;
		if(tmp!=4 && tmp!=7)
			return 0;
		x/=10;
	}
	return 1;
}
int main(void)
{
	for(int i=1;i<=13;i++)
		pre[i]=(ll)i*pre[i-1];
	scanf("%lld%lld",&n,&k);
	if(n<13 && k>pre[n])
	{
		printf("-1\n");
		return 0;
	}
	k--;ll m=min(n,13ll);
	for(int i=m;i>0;i--)
	{
		ll t=k/pre[i-1];k%=pre[i-1];
		for(int j=1;j<=m;j++)
		{
			if(!vis[j])
			{
				if(!t)
				{
					vis[j]=1;
					a[i]=n-m+j;
					break;
				}
				t--;
			}
		}
	}
	dfs(0ll,n-m);
	for(int i=1;i<=m;i++)
		if(jud(n-i+1) && jud(a[i]))
			years++;
	printf("%lld\n",ans);
	return 0;
}

Inverse Cantor Expansion

Given 61 in (1, 2, 3, 4, 5), the permutation and combination can be calculated as 34152. The above calculation process can be easily reversed, and the specific process is as follows:

  • Use 61 / 4! = 2 to add 13, indicating that a[5]=2, indicating that there are 2 numbers smaller than the first position, so the first position is 3.
  • Use 13 / 3! = 2 to add 1, indicating that a[4]=2, indicating that there are 2 numbers less than the second digit after the second digit, so the second digit is 4.
  • Use 1 / 2! = 0 plus 1, indicating that a[3]=0, indicating that there is no number less than the third digit after the third digit, so the third digit is 1.
  • Use 1 / 1! = 1 plus 0, indicating that a[2]=1, indicating that there is 1 number less than the fourth digit after the second digit, so the fourth digit is 5.
  • The last digit is naturally the remaining number 2.
  • Through the above analysis, the required permutation and combination is 34152.


#include<iostream>  
#include<cstring>  
#include<vector>
#include<algorithm>
using namespace std;  
long int factory[]={1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880}; 
void decontor(int x, int n)  {
    vector<int> v;
    vector<int> a;
    for(int i = 1; i <= n; i++) v.push_back(i);
    sort(v.begin(), v.end());
    for(int i = n-1; i >= 0; i--) {  
        int r = x % factory[i];
        int t = x / factory[i];
        x = r;
        a.push_back(v[t]);
        v.erase(v.begin()+t);
    }
    for(int i = 0; i < a.size(); i++) cout << a[i];                          
}  
int main()  
{  
      int x, n;
    cin >> x >> n;
    decontor(x, n);   
    return 0;  
}

Guess you like

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