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 }