IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    BZOJ3301: [USACO2011 Feb] Cow Line

    wyfcyx发表于 2015-08-18 19:34:33
    love 0

    题目大意:

    (1)给定一个排列,问排列的序号.

    (2)给定一个序号,要求构造出给定序号的排列.

    题解:

    首先要知道怎么得出排列的序号.

    假如序列的长度为$n$,且第$i$个元素为$P_i$.

    则序号为:$\sum_{i=1}^{n}(n-i)!\sum_{j=i+1}^{n}[P_i>P_j]$

    这样的话可以$O(n^2)$算出排列的序号.

    构造序列的话也是一个道理,我是暴力的,没管复杂度...

    代码:

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<climits>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef unsigned long long llu;
    
    int a[21],ans[21];
    llu fac[21];
    bool ok[21];
    int main(){
    	int n,Q,i,j;
    	char s[10];
    	cin>>n>>Q;
    	llu x;
    	for(fac[0]=i=1;i<=20;++i)
    		fac[i]=fac[i-1]*i;
    	int temp;
    	while(Q--){
    		scanf("%s",s);
    		if(s[0]=='P'){
    			cin>>x;
    			--x;
    			for(i=1;i<=n;++i)
    				a[i]=x/fac[n-i],x-=a[i]*fac[n-i];
    			memset(ok,1,sizeof ok);
    			for(i=1;i<=n;++i){
    				temp=0;
    				for(j=1;j<=n;++j){
    					if((temp+=ok[j])==a[i]+1)
    						break;
    				}
    				ok[ans[i]=j]=0;
    			}
    			for(i=1;i<=n;++i){
    				if(i!=1)
    					putchar(' ');
    				printf("%d",ans[i]);
    			}
    			puts("");
    		}
    		else{
    			for(i=1;i<=n;++i)
    				scanf("%d",&a[i]);
    			for(x=0,i=1;i<=n;++i){
    				for(temp=0,j=i+1;j<=n;++j)
    					temp+=(a[i]>a[j]);
    				x+=fac[n-i]*temp;
    			}
    			cout<<x+1<<endl;
    		}
    	}
    	return 0;
    }


沪ICP备19023445号-2号
友情链接