bzoj 3301 Cow Line

题目大意:

n的排列,K个询问

为P时,读入一个数x,输出第x个全排列

为Q时,读入N个数,求这是第几个全排列

思路:

不知道康拓展开是什么,手推了一个乱七八糟的东西

首先可以知道

把排列看成是一个每一位进制不同的数

每一位进制可以看做是:

(n-1)!   (n-2)!  ...... 2 1 1 

然后对于第一种询问

像正常进制转换一样,处理出每一位应该填第几个数

这时需要处理一下哪些数可以被取到

然后取可以取到的数里的第“几”个 每一位输出就可以了

对于第二种询问

直接一位一位减,同样在处理的时候记录哪些数可以被取到

答案+=每一位进制*该位置权值

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 100100
12 using namespace std;
13 inline ll read()
14 {
15     ll x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 ll n,T,t[22],x,pos,vis[22],i,cnt,tot,res,f;
21 char ch[2];
22 int main()
23 {
24     n=read();
25     t[n]=t[n-1]=1;
26     for(i=n-2;i;i--) t[i]=t[i+1]*(n-i);
27     //cout<<t[1]<<endl;
28     for(T=read();T;T--)
29     {
30         scanf("%s",ch);
31         pos=1,tot=f=0;
32         memset(vis,0,sizeof(vis));
33         if(ch[0]=='P')
34         {
35             x=read()-1;
36             while(x)
37             {
38                 while(x<t[pos]) 
39                 {
40                     for(i=1;i<=n;i++) if(!vis[i])
41                     {
42                         if(f) printf(" %lld",i);else {printf("%lld",i);f=1;}
43                         break;
44                     }
45                     vis[i]=1;
46                     pos++;
47                 }
48                 while(x>=t[pos]) x-=t[pos],cnt++;
49                 for(i=1;i<=n&&cnt!=-1;i++) if(!vis[i]) cnt--;
50                 vis[i-1]=1,tot++,cnt=0,pos++;
51                 if(f) printf(" %lld",i-1);else {printf("%lld",i-1);f=1;}
52             }
53             if(tot!=n)
54                 for(i=1;i<=n;i++)
55                     if(!vis[i])
56                         if(f) printf(" %lld",i);else {printf("%lld",i);f=1;}
57             puts("");
58         }
59         else
60         {
61             res=0;
62             for(i=1;i<=n;i++) 
63             {
64                 x=read();
65                 for(ll j=1;j<x;j++) if(!vis[j]) cnt++;
66                 res+=t[i]*cnt;
67                 vis[x]=1,cnt=0;
68             }
69             printf("%lld\n",res+1);
70         }
71     }
72 }
View Code
posted @ 2018-03-09 19:42  jack_yyc  阅读(132)  评论(0编辑  收藏  举报