HAOI2015
一颗树上有 n 个点,让你将 m 个点染成黑色,使得颜色相同的点间的路径长度和最大
树形dp
F[i,j] 表示以 i 为根的子树选了 j 个黑点,子树内的所有被标记过的路径权值和
void DFS(int p,int fa)
{
static LL tmp[maxn];
fill(dp[p]+2,dp[p]+n+1,-INF);
size[p]=1;
for(int i=start[p];i;i=next[i])
if(to[i]!=fa)
{
int q=to[i];
DFS(to[i],p);
fill(tmp,tmp+size[p]+size[q]+1,-INF);
for(int j=0;j<=size[p];++j)
for(int k=0;k<=size[q];++k)
tmp[j+k] = max(tmp[j+k],dp[p][j]+dp[q][k]+len[i]*(k*(m-k)+(size[q]-k)*(n-m-(size[q]-k))));
size[p]+=size[q];
for(int j=0;j<=size[p];++j)
dp[p][j]=tmp[j];
}
}
注意写的顺序,不然可能会T
需要的知识:树形DP
T2
裸的树链剖分,大家都写过。。。
T3
暴力30分没拿到TAT
如果你推出了SG函数,然后你就拿到了50分啦。。。
由数学归纳法(其实是打表),得到对于 N/i 相同的 N ,SG函数都相同,这样最多只有 sqrt(n) 块,然后可以二分查找了,T到70分。。。
发现对于70分的算法,相邻两块也有很多的值是一样的,然后就又可以优化了。。。
100标算没看懂TAT,70分的基础上搞一搞勉强水过。。。
复杂度:O(玄学)
需要的知识:SG函数
T4 set
变换与变回:
for(int i=0;i<n;++i)
for(int j=0;j<N;++j)
if(j>>i&1)
a[j]+=a[j^(1<<i)];
for(int i=0;i<n;++i)
for(int j=0;j<N;++j)
if(j>>i&1)
a[j]-=a[j^(1<<i)];
orz gjy
需要的知识:容斥
T5
对于 f (n) 有 f(n) = ∑ f(i) (max(0 , n-m) <= i < n)
显然我们可以得到一个m * m的矩阵 A 来求得f(n)
因为矩阵具有分配律和可加性 所以有 A * (B+C) = A * B + A * C
A ^ (x1 + x2 + ...... xn) = A ^ x1 * A ^ x2 * ...... * A ^ xn
ans = ∑ (A * B) = ( ∑ A )* B
求 ∑A 时可以用dp
先预处理出每一段的 A^x 值记为seg[i,j]
状态转移: f[i]=∑ f[j] * seq[j+1][i] (j < i)
最后再乘上矩阵 B 就行了