zoukankan      html  css  js  c++  java
  • 康托展开(学习笔记)

    大佬博客

    就两个内容,一个是康托展开,一个是逆康托展开.即前者是给定一个(n)个数的排列,求这个排列在这(n)个数的全排列中 按照字典序从小到大 是排在第几个.后者是给定排名,求出其对应的排列.

    知识点看上面那篇博客就能懂了.这里只提个醒,就是不论是康托展开,还是逆康托展开,我们求出的排名都是指排在这个排列的前面的排列有多少个.即假设在康托展开中,对于一个排列(p),我们按照公式求出了一个数(x),(x)表示的是(p)前面的排列有多少个,即(p)的排名是(x+1).同理在逆康托展开中,给定了排名(k),我们应该先让(k-1),然后再去套公式求出其对应的排列.

    洛咕:【模板】康托展开

    题意:求(1sim N)的一个给定全排列在所有(1sim N)全排列中的排名。结果对(998244353)取模.(1<=N<=1000000.)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=1e6+5;
    const int mod=998244353;
    int n,a[N],c[N];ll ans,jc[N];
    inline void add(int x){for(;x<=n;x+=x&-x)++c[x];}
    inline int ask(int x){int cnt=0;for(;x;x-=x&-x)cnt+=c[x];return cnt;}
    int main(){
    	n=read();for(int i=1;i<=n;++i)a[i]=read();
    	jc[0]=1;for(int i=1;i<=n;++i)jc[i]=(1ll*jc[i-1]*i)%mod;
    	for(int i=1;i<=n;++i){
    		int sum=ask(a[i]);
    		ans=(ans+1ll*(a[i]-1-sum)*jc[n-i]%mod)%mod;
    		add(a[i]);
    	}
    	printf("%lld
    ",ans+1);
        return 0;
    }
    
    

    洛咕:[(USACO11FEB)]牛线(Cow) (Line)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    int a[30],bj[30];ll jc[30];
    int main(){
    	int n=read(),T=read();
    	jc[0]=1;for(int i=1;i<n;++i)jc[i]=1ll*jc[i-1]*i;
    	while(T--){
    		char ch;cin>>ch;
    		if(ch=='P'){//逆康托展开
    			ll k=read()-1;
    			for(int i=1;i<=n;++i)bj[i]=0;
    			for(int i=1;i<=n;++i){
    				int res=k/jc[n-i];k%=jc[n-i];
    				int cnt=0;
    				for(int j=1;j<=n;++j){
    					if(bj[j])continue;
    					if(cnt==res){printf("%d ",j);bj[j]=1;break;}
    					else ++cnt;
    				}
    			}
    			printf("
    ");
    		}
    		if(ch=='Q'){//康托展开
    			ll ans=0;
    			for(int i=1;i<=n;++i)a[i]=read();
    			for(int i=1;i<n;++i){
    				int sum=0;
    				for(int j=i+1;j<=n;++j)if(a[i]>a[j])++sum;
    				ans=ans+1ll*sum*jc[n-i];
    			}
    			printf("%lld
    ",ans+1);
    		}
    	}
        return 0;
    }
    
    

    洛咕:(Uim)的情人节礼物·其之弐

    洛咕:(Uim)的情人节礼物·其之壱

  • 相关阅读:
    数独游戏 C++ 回溯法
    DirectX 90 3D 网格一
    DirectX 90 3D SetRenderState 设置渲染状态
    DirectX90 3D 字体
    DirectX 90 3D 外接体
    VS2005下配置OGRE
    DirectX 90 3D 网格二
    Java反射机制
    UBUNTU下安装 APACHE+PHP+MYSQL文本服务器!
    关于那个SMTP类及一个例子
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11861790.html
Copyright © 2011-2022 走看看