定义深度为到根的边权和,考虑按深度 dp,显然深度小的放的是出现次数较多的数
即放得是一个后缀,记录 dpi,a,b,c 表示到第 i 层当前层有 a 个,下一层可以放 b 个,选的后缀为 c 的最小值,枚举多少个后缀放当前层,对应转移到 dpi+1,b+(a−t),a−t,c+t,系数是 i∗t
系数可以提前计算,于是可以压掉层数一维,对应转移到 dpb+a−t,a−t,c+t,系数是 ∑i=1cai
考虑将后缀一个一个加入,枚举是当前层还是下一层,到当前层是一个完全揹包,复杂度 O(n3)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
cs int N =755;int n; ll c[N], dp[2][N][N];
void ckmin(ll &a, ll b){if(a > b) a = b;}intmain(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%d",&n);for(int i=1; i<=n; i++)scanf("%lld",&c[i]);sort(c+1,c+n+1);for(int i=1; i<=n; i++) c[i]+=c[i-1];int now=0, nxt=1;memset(dp[now],0x3f,sizeof(dp[now]));
dp[now][1][1]= c[n];for(int i=n; i>=1; i--){memset(dp[nxt],0x3f,sizeof(dp[nxt]));for(int j=0; j<=i; j++)for(int k=0; j+k<=i; k++)ckmin(dp[now][j+k][j],dp[now][j][k]+c[i]);for(int j=1; j<=i; j++)for(int k=0; j+k<=i; k++)ckmin(dp[nxt][j-1][k],dp[now][j][k]);swap(now,nxt);} cout<<dp[now][0][0];return0;}
B
考虑两个 11 直接不可能到达,状态较少,可以通过
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
cs int N =80;int Mod, iv2, iv4;intadd(int a,int b){return a + b >= Mod ? a + b - Mod : a + b;}intdec(int a,int b){return a - b <0 ? a - b + Mod : a - b;}intmul(int a,int b){return1ll * a * b % Mod;}
void Add(int&a,int b){ a =add(a,b);}
void Mul(int&a,int b){ a =mul(a,b);}
void Dec(int&a,int b){ a =dec(a,b);}intksm(int a,int b){int as=1;for(;b;b>>=1,Mul(a,a))if(b&1)Mul(as,a);return as;}int n; typedef bitset<N> bs;
namespace table{
cs int M =19260817;int fi[M], nxt[M], v[M], ec; bs w[M];
void ins(bs x,int vl){int t=0;for(int i=0; i<n; i++) t=(ll)(t*31+x[i])%M;
nxt[++ec]=fi[t]; fi[t]=ec,swap(w[ec],x), v[ec]=vl;
t=0;for(int i=n-1;~i;i--) t=(ll)(t*31+x[i])%M;
nxt[++ec]=fi[t]; fi[t]=ec,swap(w[ec],x), v[ec]=vl;}intask(bs x){int t=0;for(int i=0; i<n; i++) t=(ll)(t*31+x[i])%M;for(int e=fi[t];e;e=nxt[e])if(w[e]==x)return v[e];return-1;}}
void cover(bs&x){int l=n+1,r=-1;for(int i=1;i+1<n;i++)if(x[i]&&x[i+1])l=min(l,i),r=max(r,i);for(int i=l; i<=r+1; i++) x.set(i);}intdfs(bs x){if(x.test(0))return0;
x.set(0);cover(x);int t = table::ask(x);if(~t)return t;int ans =0;
bs nx = x>>1;if(x.test(0)) nx.set(n-1);Add(ans,dfs(nx));
nx = x>>2;if(x.test(0)) nx.set(n-2);if(x.test(1)) nx.set(n-1);Add(ans,dfs(nx));
nx = x<<1;if(x.test(n-1)) nx.set(0);Add(ans,dfs(nx));
nx = x<<2;if(x.test(n-1)) nx.set(1);if(x.test(n-2)) nx.set(0);Add(ans,dfs(nx));Mul(ans,iv4);Add(ans,1);return ans;}intmain(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%d%d",&n,&Mod);
iv2 =(Mod+1)>>1; iv4 =mul(iv2,iv2);if(n==1)returnputs("1"),0;
cout <<dfs(bs());return0;}