2013多校第六场

hdu 4655

题意:给一个序列,每个位置可以涂1~ai种颜色,连续不相同的颜色为一段,对于一个排列,所有的涂色方法产生的段数为S,求最大的S;

分析:对于一个排序,所有的段数为n*{a1*a2*...*an} - (相邻两个位置涂相同颜色的个数S);

怎么计算相邻两个位置涂相同颜色的个数S?

p[i]表示前缀积,即p[i] = a1*a2*..*ai; 

q[i]表示后缀积,即q[i] = ai*...*an;

S =sum( p[i-1]*q[i+2]*min(ai,ai+1) ) (0<=i<n);即如果相邻两个相等就减去一;

要使S最小,即min(ai,ai+1)尽量小,假设序列ai<ai+1,a1,an,a2,an-1...就是最优序列;

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cmath>
 7 using namespace std;
 8 typedef long long LL;
 9 const int Mod = (int)1e9+7;
10 const int N = 1000000+10;
11 int a[N],b[N];
12 int n;
13 LL p[N],q[N];
14 int main(){
15     int T; scanf("%d",&T);
16     while (T--) {
17         scanf("%d",&n);
18         for (int i = 0; i < n; i++) {
19             scanf("%d",&a[i]);
20         }
21         sort(a,a+n);
22         int l = 0, r = n - 1;
23         for (int i = 0; i < n; i++) {
24             if (i%2 == 0) {
25                 b[i] = a[l++];
26             }else b[i] = a[r--];
27          //   cout<<b[i]<<" ";
28         }//cout<<endl;
29         LL sum = n;
30         p[0] = b[0]; q[n] = 1;
31         for (int i = 1; i < n; i++) p[i] = p[i-1] * b[i] % Mod;
32         for (int i = n-1; i >= 0; i--) q[i] = q[i+1] * b[i] % Mod;
33         for (int i = 0; i < n; i++) sum = sum * b[i] % Mod;
34         sum = (sum - (LL)min(b[0],b[1])*q[2]%Mod + Mod ) % Mod;
35         for (int i = 1; i < n-1; i++) {
36             sum = (sum - p[i-1]*q[i+2] % Mod * min(b[i],b[i+1]) % Mod + Mod ) % Mod;
37         }
38         cout<<sum<<endl;
39     }
40 
41     return 0;
42 }
View Code

 

posted @ 2013-08-09 10:57  Rabbit_hair  阅读(244)  评论(0)    收藏  举报