HDU 5225 枚举

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5225

bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=580&pid=1002

题解:

数组a保存输入

考虑当前位i,对于1<=j<i,使得x[j]=a[j],对于第i位,枚举1<=x[i]<a[i],并且x[i]!=x[j](1<=j<i),这样,对于i<j<=n的部分,任意排列都是满足条件的

这样,我们每次计算逆序对可以分为三个部分:

1~i-1的贡献:

  计算出所有的a[j](即x[j])>a[k]的个数(1<=j<=i-1,j<k<=n)cnt1(可预处理出来)

第i位的贡献:

  计算出所有的x[i]>a[k] (i<k<=n) cnt2

由上面两部分得:1~i的贡献:cnt12 =(cnt1+cnt2)*(n-i)!

最后考虑i+1~n的逆序对:

  在后n-i个位置中,有一半的排列方式中,第j小的数在第k小的数(j>k)的前面。共有(n-i)!种排列方式,所以对于一对数,有(n-i)!/2种排列方式中是逆序对。共有(n-i)*(n-i-1)/2对数,所有这类逆序对共(n-i)*(n-i-1)*(n-i)!/4对。

  即cnt3=(n-i)*(n-i-1)*(n-i)!/4

综上:第i位的答案是cnt12+cnt3;

注意:

  cnt3=(n-i)*(n-i-1)*(n-i)!/4,这里的4要在取模之前处理掉!!!取模之前处理掉!!!取模之前处理掉!!!

  总共4天提交了11次,CE了2次,wa了6次,ac了3次,最后一次ac告诉我,三天前错的地方就只有一个!除4没有提前处理!!!

代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 const int maxn = 100 + 10;
 7 const int mod = 1e9 + 7;
 8 typedef long long LL;
 9 
10 int arr[maxn], used[maxn];
11 
12 int n;
13 
14 LL cnt[maxn];
15 void pre_for_solve() {
16     memset(cnt, 0, sizeof(cnt));
17     for (int i = 1; i <= n; i++) {
18         cnt[i] = cnt[i - 1];
19         for (int j = i + 1; j <= n; j++) {
20             if (arr[i]>arr[j]) cnt[i]++;
21         }
22     }
23 }
24 
25 LL fac[maxn], fac2[maxn];
26 void get_fac() {
27     memset(fac, 0, sizeof(fac));
28     memset(fac2, 0, sizeof(fac2));
29     //求1*3*4*...*n
30     fac[0] = 1, fac[1] = 1, fac[2] = 1;
31     for (int i = 3; i < maxn; i++) {
32         fac[i] = fac[i - 1] * i%mod;
33     }
34     //求1*2*3...*n
35     fac2[0] = 1;
36     for (int i = 1; i<maxn; i++) {
37         fac2[i] = fac2[i - 1] * i%mod;
38     }
39 }
40 
41 void init() {
42     memset(used, 0, sizeof(used));
43 }
44 
45 int main() {
46     get_fac();
47     while (scanf("%d", &n) == 1 && n) {
48         init();
49         for (int i = 1; i <= n; i++) scanf("%d", arr + i);
50         pre_for_solve();
51         LL ans = 0;
52         for (int i = 1; i <= n; i++) {
53             for (int x = 1; x<arr[i]; x++) {
54                 if (!used[x]) {
55                     //cnt1
56                     LL sum = cnt[i - 1];
57                     //cnt2
58                     for (int xx = 1; xx <= n; xx++) {
59                         if (!used[xx] && x>xx) sum++;
60                     }
61                     //cnt12
62                     sum = sum*fac2[n - i] % mod;
63                     //cnt3
64                     LL tmp = fac[n - i] * (n - i)*(n - i - 1) / 2 % mod;
65                     //cnt12+cnt3
66                     sum = (sum + tmp) % mod;
67                     ans += sum;
68                     ans %= mod;
69                 }
70             }
71             used[arr[i]] = 1;
72         }
73         printf("%lld\n", ans);
74     }
75     return 0;
76 }

 

posted @ 2016-04-18 23:03  fenicnn  阅读(394)  评论(0编辑  收藏  举报