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.
输入输出样例
5 2 P 3 Q 1 2 5 3 4
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; 求它的全排列
核心是这样的一张图
第一次 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) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现