HDU 4655 Cut Pieces

假设n个数构成的总数都分成了n段,总数是n*a1*a2*...*an。但是答案显然不会那么多。

对于相邻的两个ai,ai+1,如果选择相同的颜色,那么就减少了a1*a2*...*ai-1*min(ai,ai+1)*ai+2*ai+3*...*an

不妨假设n=3,三个数分别是a,b,c。且a<b<c。

对于所有的排列,只有a,c,b是最优的,结果是3*a*b*c-a*b-b。

当n>3的时候同样可以得到结论:a1,an,a2,an-1...使得总的段数最多。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 typedef long long LL;
 5 #define MOD 1000000007
 6 #define MAXN 1000010
 7 using namespace std;
 8 int arr[MAXN];
 9 int tmp[MAXN];
10 LL ext_gcd(LL a, LL b, LL &x, LL &y) {
11     LL t, d;
12     if (b == 0) {
13         x = 1;
14         y = 0;
15         return a;
16     }
17     d = ext_gcd(b, a % b, x, y);
18     t = x;
19     x = y;
20     y = t - a / b * y;
21     return d;
22 }
23 LL invmod(LL a, LL n = MOD) {
24     LL x, y;
25     if (ext_gcd(a, n, x, y) != 1)
26         return -1;
27     return (x % n + n) % n;
28 }
29 int main() {
30     int T;
31     int n;
32     int i;
33     LL ans;
34     LL res;
35     LL mul;
36     int l, r;
37     scanf("%d", &T);
38     while (T--) {
39         scanf("%d", &n);
40         ans = n;
41         mul = 1;
42         for (i = 0; i < n; i++) {
43             scanf("%d", &arr[i]);
44             mul *= arr[i];
45             mul %= MOD;
46         }
47         ans *= mul;
48         ans %= MOD;
49         sort(arr, arr + n);
50         for (l = 0, r = n - 1, i = 1; l <= r; l++, r--) {
51             if (l == r) {
52                 tmp[i++] = arr[l];
53             } else {
54                 tmp[i++] = arr[l];
55                 tmp[i++] = arr[r];
56             }
57         }
58         for (i = 2; i <= n; i++) {
59             res = mul * invmod(tmp[i] * (LL) tmp[i - 1]);
60             res %= MOD;
61             res *= min(tmp[i], tmp[i - 1]);
62             ans -= res % MOD;
63             ans = (ans % MOD + MOD) % MOD;
64         }
65         cout << ans << endl;
66     }
67     return 0;
68 }
View Code

相关文章: