P3014 [USACO11FEB]牛线Cow Line

题目描述

The N (1 <= N <= 20) cows conveniently numbered 1...N are playing yet another one of their crazy games with Farmer John. The cows will arrange themselves in a line and ask Farmer John what their line number is. In return, Farmer John can give them a line number and the cows must rearrange themselves into that line.

A line number is assigned by numbering all the permutations of the line in lexicographic order.

Consider this example:

Farmer John has 5 cows and gives them the line number of 3.

The permutations of the line in ascending lexicographic order: 1st: 1 2 3 4 5

2nd: 1 2 3 5 4

3rd: 1 2 4 3 5

Therefore, the cows will line themselves in the cow line 1 2 4 3 5.

The cows, in return, line themselves in the configuration '1 2 5 3 4' and ask Farmer John what their line number is.

Continuing with the list:

4th : 1 2 4 5 3

5th : 1 2 5 3 4

Farmer John can see the answer here is 5

Farmer John and the cows would like your help to play their game. They have K (1 <= K <= 10,000) queries that they need help with. Query i has two parts: C_i will be the command, which is either 'P' or 'Q'.

If C_i is 'P', then the second part of the query will be one integer A_i (1 <= A_i <= N!), which is a line number. This is Farmer John challenging the cows to line up in the correct cow line.

If C_i is 'Q', then the second part of the query will be N distinct integers B_ij (1 <= B_ij <= N). This will denote a cow line. These are the cows challenging Farmer John to find their line number.

输入输出格式

输入格式:

 

  • Line 1: Two space-separated integers: N and K

  • Lines 2..2*K+1: Line 2*i and 2*i+1 will contain a single query.

Line 2*i will contain just one character: 'Q' if the cows are lining up and asking Farmer John for their line number or 'P' if Farmer John gives the cows a line number.

If the line 2*i is 'Q', then line 2*i+1 will contain N space-separated integers B_ij which represent the cow line. If the line 2*i is 'P', then line 2*i+1 will contain a single integer A_i which is the line number to solve for.

 

输出格式:

 

  • Lines 1..K: Line i will contain the answer to query i.

If line 2*i of the input was 'Q', then this line will contain a single integer, which is the line number of the cow line in line 2*i+1.

If line 2*i of the input was 'P', then this line will contain N space separated integers giving the cow line of the number in line 2*i+1.

 

输入输出样例

输入样例#1:
5 2 
P 
3 
Q 
1 2 5 3 4 
输出样例#1:
1 2 4 3 5 
5 

题意:

有N头牛,和K个询问

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

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

通过康托展开 求第x个全排列 求某个全排列是第几个

对于n个数的全排列
康托展开

ai代表第i个元素在未出现的元素中是第几大 即在第i~n位的元素中排第几

对与 2 1 3
对于 2 只有1比它大 所以排第1大
对于 1 没有比它大的 所以排第0大
对于 3 没有和它比较的 所以排第0大
a3=3 a2=0a1=0

ans=3;

康托展开逆运算
已知某一全排列在所有排列中排第x
可以求得 这个全排列

例如 ans=20; 求它的全排列
核心是这样的一张图
Cantor

第一次 20/(3!) =3……2 说明在第一个元素后面有3个比现在的元素小 这个元素就是4
第二次 2/(2!) =1……0 说明在这个元素后面有一个比它小 这只能是2
第三次 0/(1!) =0……0 说明这个元素后面没有比它小的 只能是 1
第四次 0/(0!) =0……0 只剩3了


 1 /*
 2     把1 2 3 4 5 视为第0种排列
 3       1 2 3 5 4 视为第1种排列 
 4     所以寻找第x种排列时 x 要减1
 5     
 6     同理 ans要加1 
 7 */
 8 #include <vector>
 9 #include <cctype>
10 #include <cstdio>
11 #include <iostream>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 typedef long long LL;
17 
18 const int MAXN=30;
19 
20 int n,m;
21 
22 int s[MAXN];
23 
24 LL a[MAXN];
25 
26 char c[5];
27 
28 inline void read(int&x) {
29     int f=1;register char c=getchar();
30     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
31     for(;isdigit(c);x=x*10+c-48,c=getchar());
32     x=x*f;
33 }
34 
35 inline LL The_num() {
36     LL ans=0;
37     for(int i=1;i<=n;++i) {
38         int t=0;
39         for(int j=i+1;j<=n;++j) 
40           if(s[i]>s[j]) ++t;
41         ans+=t*a[n-i];
42     }
43     return ans;
44 }
45 
46 inline void The_permutation(LL k) {
47     --k;
48     vector<int> v,ans;
49     for(int i=1;i<=n;++i) 
50       v.push_back(i);
51     for(int i=n;i>=1;--i) {
52         LL r=k%a[i-1];
53         LL b=k/a[i-1];
54         k=r;
55         sort(v.begin(),v.end());
56         ans.push_back(v[b]);
57         v.erase(v.begin()+b);
58     }
59     vector<int>::iterator it;
60     for(it=ans.begin();it!=ans.end();++it) 
61       printf("%d ",*it);
62     printf("\n");
63     return;
64 }
65 
66 int hh() {
67 //    freopen("permutation.in","r",stdin);
68 //    freopen("permutation.out","w",stdout);
69     LL x;
70     read(n);read(m);
71     a[0]=1;
72     for(int i=1;i<=n;++i) a[i]=a[i-1]*i;
73     for(int i=1;i<=m;++i) {
74         scanf("%s",c);
75         if(c[0]=='P')  {
76             cin>>x;
77             The_permutation(x);
78         }
79         else if(c[0]=='Q') {
80             for(int j=1;j<=n;++j) read(s[j]);
81             LL ans=The_num();
82             printf("%lld\n",ans+1);
83         }
84     }
85     return 0;
86 }
87 
88 int sb=hh();
89 int main(int argc,char**argv) {;}
代码

 







posted @ 2017-09-06 15:51  拿叉插猹哈  阅读(137)  评论(0编辑  收藏  举报