[東南大學第2屆程式設計秋季賽 G] Hmmm: A Tricky Counting Challenge - 結論,思維,dp
阿新 • • 發佈:2020-11-29
Description
定義一個長度為 \(n (n \ge 2)\) 的正整數數列 \(a_1,a_2,...,a_n\) 的權值為
\[F(a_1,a_2,...,a_n)=\sum_{i=2}^{n-1} \max(\min(\max_{j=1}^{i-1} (a_j-a_i), \max_{j=i+1}^n (a_j-a_i)), 0) \]給定一個長度為 \(n\) 的正整數數列 \(a_1,a_2,...,a_n\)。
定義一種交換操作:任意選擇兩個下標 \(i,j\) 滿足 \(1 \le i < j \le n\),交換 \(a_i,a_j\) 的值。
定義一個自然數 \(z\)
簡而言之,即求對於給定數列通過任意次交換操作得到的所有數列中,數列權值的不同可能取值有多少種。
第一行一個整數 \(n (1 \le n \le 500)\) 表示數列的長度。
第二行 \(n\) 個正整數,第 \(i\) 個正整數表示 \(a_i ( 1 \le a_i \le 50)\)。注意數列中可能會有相同的數。
Solution
以下數列 \(\{a_i\}\) 指的均是原數列的任意一種排列。設
\[b_1=a_1,b_n=a_n,b_i = \max(\min(\max_{j=1}^{i-1} a_j, \max_{j=i+1}^n a_j), a_i) (2 \le i \le n) \]由 \(\{a_i\}\) 得到 \(\{b_i\}\) 的過程稱為一次變換。對於任意一個數列 \(a_i\),對 \((a_i,b_i)\) 進行排序使 \(b_i\) 單調不升並且 \(b_i\) 相同時 \(a_i\) 單調不降,結果記做 \((a'_i,b'_i)\),則 \(b'_i\) 仍是 \(a'_i\) 經過變換後的序列。利用動態規劃統計所有可能的 \(\{b'_i\}\)
std::bitset
優化即可。
改編自 [CCO 2017] 接雨滴
#include <bits/stdc++.h>
using namespace std;
#define int long long
bitset <30005> f[505],ans;
int n,a[505],sum,res;
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i], sum+=a[i];
sort(a+1,a+n+1,greater<int>());
f[1][a[1]]=1;
for(int i=2;i<=n;i++,ans|=f[n]) for(int j=i;j<=n;j++) f[j]|=f[j-1]<<a[i];
for(int i=sum;i<30005;i++) res+=ans[i];
cout<<res;
}