[數位DP]luogu P3646 [APIO2015]巴厘島的雕塑
阿新 • • 發佈:2021-03-25
題面
https://www.luogu.com.cn/problem/P3646
分析
直接得到最終優美度是顯然不可做的,注意到二進位制位數並不多,考慮從高位逐位計算
設方程 f[i][j] 表示分組完第 i 個數,用了 j 組,最終優美度能否為 0
目前列舉到第 k 位,那麼 k+1~maxbit 的位上已經確定了 0 1 了
我們考慮把當前這位欽定為 0 ,高位符合已確定的值,則低位可以任意
這時候就可以用簡單的 O(n^3) DP完成轉移,如果存在 $f[n][i] (i\in [A,B])$ 為真,則該位可以為 0 ,否則為 1
轉移方程: $f[i][j]|=f[k][j-1]|(sum_{k+1~i}滿足當前位為0,高位符合已確定值)$
發現對於子任務 5 無法通過,再觀察性質:A=1
則不需要判斷是否存在$f[n][i] (i\in [a,b])$ 為真,只需要設 g[i] 表示選擇到第 i 個滿足限制的最小分組數,有 $g[n]\leq B$ 該位即可為 0
分任務通過
程式碼
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std; typedef long long ll; const int N=2e3+10; int n,a,b,bit; ll y[N]; int f[N][N]; ll DP1() { ll ans=0; for (ll i=1ll<<bit;i;i>>=1) { bool zerable=0;memset(f,0,sizeof f);f[0][0]=1; for (int j=1;j<=n;j++) for (int k=1;k<=min(j,b);k++) for (int l=j-1;l>=k-1;l--) { f[j][k]=(f[l][k-1]&&((ans|i-1ll)|y[j]-y[l])==(ans|i-1ll)); if (f[j][k]) break; } for (int j=a;j<=b;j++) if (f[n][j]) {zerable=1;break;} if (!zerable) ans|=i; } return ans; } ll DP2() { ll ans=0; for (ll i=1ll<<bit;i;i>>=1) { bool zerable=0; f[0][0]=0;for (int j=1;j<=n;j++) f[j][0]=n+1; for (int j=1;j<=n;j++) for (int l=j-1;l>=0;l--) if (((ans|i-1ll)|y[j]-y[l])==(ans|i-1ll)) f[j][0]=min(f[j][0],f[l][0]+1); if (f[n][0]>b) ans|=i; } return ans; } int main() { scanf("%d%d%d",&n,&a,&b); for (int i=1;i<=n;i++) scanf("%lld",&y[i]),y[i]+=y[i-1];bit=log2(y[n])+1; printf("%lld\n",(a!=1)?DP1():DP2()); }
&n