Next K Permutation

3457: Next K Permutation

时间限制: 1 Sec  内存限制: 128 MB
提交: 4  解决: 4
[提交] [状态] [讨论版] [命题人:admin]

题目描述

n 个数有 n! 种全排列情况,对所有排列排序后求第 L 个到第 R 个排列中逆序对数量之和。
逆序对定义(摘自 wiki):

设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。
如果存在正整数 i,j 使得 1≤i<j≤n 而且 Ai>Aj,则 (Ai,Aj) 这一个有序对称为 A 的一个逆序对,也称作逆序。逆序对的数量称作逆序数。

 

输入

第一行 case 数量 T。
接下来每一行有 3 个数,n,L,R (3≤n≤12,1≤L≤R≤109)。

 

输出

输出逆序对总数。

 

样例输入

3
3 3 5
6 720 720
8 14625 17743

样例输出

5
15
38745

 

提示

样例 1 说明:
3 个数所有排列排序后及其逆序对个数:
    (1,2,3): 0;
    (1,3,2): 1;
    (2,1,3): 1;
    (2,3,1): 2;
    (3,1,2): 2;
    (3,2,1): 3.
第 3 个到第 5 个排列逆序对数量之和为 1+2+2=5。

 

来源/分类

 2017 华东理工上海高校邀请赛  

题解:详见代码!!!

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll jie_cheng[20],ni_xu_shu[20];
 5 void init()
 6 {
 7     jie_cheng[0]=ni_xu_shu[0]=ni_xu_shu[1]=0;
 8     jie_cheng[1]=1;
 9     for(ll i=2;i<=12;i++)
10     {
11         jie_cheng[i]=jie_cheng[i-1]*i;
12         ni_xu_shu[i]=jie_cheng[i-1]*((i-1)*i/2)+ni_xu_shu[i-1]*i;//长度为i的序列(每个数字都不同)所有排列的逆序数总和
13     }
14 }
15 ll solve(int n,ll k)
16 {
17     ll res=0;
18     int prefix[20];
19     for(int i=1;i<=n;i++)//枚举前缀长度
20     {
21         for(int j=1;j<=n;j++)//枚举前缀元素
22         {
23             bool flag=true;
24             for(int s=1;s<i;s++)
25             {
26                 if(prefix[s]==j)//出现过的元素就不能再出现
27                 {
28                     flag=false;
29                     break;
30                 }
31             }
32             if(!flag) continue;
33             prefix[i]=j;
34             if(k<jie_cheng[n-i]) break;
35             else
36             {
37                 k-=jie_cheng[n-i];
38                 res+=ni_xu_shu[n-i];
39                 ll cnt=0;
40                 for(int s=1;s<=i;s++)
41                 {
42                     for(int l=s+1;l<=i;l++)
43                     {
44                         if(prefix[s]>prefix[l])
45                         {
46                             cnt++;
47                         }
48                     }
49                 }
50                 int tmp[20];
51                 for(int s=0;s<=n;s++) tmp[s]=0;
52                 for(int s=1;s<=i;s++) tmp[prefix[s]]=1;
53                 for(int s=1;s<=n;s++)
54                 {
55                     for(int l=1;l<=s;l++)
56                     {
57                         if(tmp[s]==1 && tmp[l]==0)
58                             cnt++;
59                     }
60                 }
61                 res+=jie_cheng[n-i]*cnt;
62             }
63         }
64     }
65     return res;
66 }
67 int main()
68 {
69     init();
70     int t;
71     scanf("%d",&t);
72     while(t--)
73     {
74         int n;
75         ll l,r;
76         scanf("%d %lld %lld",&n,&l,&r);
77         printf("%lld\n",solve(n,r)-solve(n,l-1));
78     }
79     return 0;
80 }
View Code

 

posted @ 2019-01-16 22:14  Gang_Li  阅读(203)  评论(0编辑  收藏  举报