TOJ 3838: Cow Line -- 排列

3838: Cow Line

Time Limit(Common/Java):2000MS/6000MS     Memory Limit:65536KByte
Total Submit: 25            Accepted:10

Description

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.

 

Input

* 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.

 

Output

* 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.

 

Sample Input

5 2
P
3
Q
1 2 5 3 4

Sample Output

1 2 4 3 5
5

Source

USACO Feb 2011


分析:根据排列的序号k(从0开始)求排列时,设共n个数,剩下n - 1个数的全排列个数为fac[n - 1],那么排列的第一位就是k / fac[n - 1] + 1。接着找剩下的n - 1个数的第k % fac[n - 1]个排列,重复上一过程就好了。

根据排列求排列序号就完全和上面相反。比如共n个数,第一个数为k,那么排列序号 = (k - 1) * fac[n - 1] + 剩下n - 1个数的排列序号。

两个过程都是递归。

#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
           #include 
           #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #include 
                   
                     #define mp make_pair using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair 
                    
                      pii; typedef vector 
                     
                       vi; typedef vi::iterator vi_it; typedef map 
                      
                        mii; typedef priority_queue 
                       
                         pqi; typedef priority_queue 
                        
                          , greater 
                         
                           > rpqi; ll fac[22]; bool flag; bool vis[22]; int ele[22]; ll ans; void ini() { fac[0] = 1; for (int i = 1; i < 20; ++i) { fac[i] = fac[i - 1] * i; } } //k numbers left, find the number idx permutation void find_order(ll idx, int k) { if (!k) { return; } int t = idx / fac[k - 1]; int pos = 0; for (int i = 0; i <= t; ++i) { ++pos; while (vis[pos]) { ++pos; } } if (flag) { cout << " "; } else { flag = true; } cout << pos; vis[pos] = true; find_order(idx % fac[k - 1], k - 1); } //totally n numbers, currently the kth number void find_pos(int k, int n) { if (k == n) { return; } int cnt = ele[k] - 1; for (int i = 1; i < ele[k]; ++i) { if (vis[i]) { --cnt; } } ans += fac[n - k - 1] * cnt; vis[ele[k]] = true; find_pos(k + 1, n); } int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); ini(); int n, k; cin >> n >> k; while (k--) { char ch; cin >> ch; if (ch == 'P') { ll a; scanf("%I64d", &a); memset(vis, 0, sizeof(vis)); flag = false; find_order(a - 1, n); cout << endl; } else { for (int i = 0; i < n; ++i) { cin >> ele[i]; } ans = 1; memset(vis, 0, sizeof(vis)); find_pos(0, n); printf("%I64d\n", ans); } } return 0; } 
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
         
        
        
       
       
      
      
     
     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值