题意:
首先定义一个序列为Beautiful为:对 2<=i<=n-1 : a[i-1]+a[i+1] >= 2*a[i]
给定n个数,问这些数的所有排列为Beautiful的有多少个
题解:
由 a[i-1]+a[i+1] >= 2*a[i],知 a[i+1]-a[i] >= a[i]-a[i-1],
也就是说,Beautiful的序列先单减,后单增。且相邻两项之间的差在变大。
将这n个数排序。
我们用dp[lastA][preA][lastB][preB]记录下:
当单减部分最大数为lastA,次大数为preA。单增部分最大数为lastB,次大数为preB时,的方案数。
新加入一个元素时,考虑一下放在左边,放在右边。就能转移了。
code:
#include <iostream> #include <algorithm> using namespace std; typedef long long LL; #define MOD (1000000007) int n; LL dp[62][62][62][62]; //dp[last_A][pre_A][last_B][pre_B] LL a[62]; int main() { scanf("%d", &n); for (int i = 1; i <= n; i ++) { scanf("%lld", &a[i]); } //------------------------------- init sort(a + 1, a + 1 + n); int low = 1; LL tmp = 1; for (int i = 2; i <= n; i ++) { if (a[i] == a[1]) { low ++; tmp = tmp * low % MOD; } } n = n - (low - 1); for (int i = 1; i <= n; i ++) { a[i] = a[i + low - 1]; } //-------------------------------solve LL ans = 0; dp[1][0][1][0] = tmp; for (int i = 1; i <= n; i ++) { for (int j = 0; j < n; j ++) { for (int k = 1; k <= n; k ++) { for (int t = 0; t < n; t ++) { int nxt = max(i, k) + 1; if (nxt == n+1) { (ans += dp[i][j][k][t]) %= MOD; continue; } // the next element joins A if ( a[nxt] - a[i] >= a[i] - a[j] || j == 0) ( dp[nxt][i][k][t] += dp[i][j][k][t] ) %= MOD; // the next element joins B if ( a[nxt] - a[k] >= a[k] - a[t] || t == 0) ( dp[i][j][nxt][k] += dp[i][j][k][t] ) %= MOD; } } } } //------------------------------------ cout << ans << endl; }