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 }