Codeforces771C: Bear and Tree Jumps-树形DP-算贡献经典题变形

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

Catalog

Problem:Portal传送门

 原题目描述在最下面。
 求 ni=2i1j=1(dis[i][j]/k) ∑ i = 2 n ∑ j = 1 i − 1 ( ⌈ d i s [ i ] [ j ] / k ⌉ ) .

Solution:

这里写图片描述
树形DP:
 当k等于1时,答案就是每条边算贡献, ans+=sum[u]×(nsum[u]) a n s + = s u m [ u ] × ( n − s u m [ u ] )
 化简: L/k=(L+f(L,k))/kf(L,k)=kL%k ⌈ L / k ⌉ = ( L + f ( L , k ) ) / k f ( L , k ) = k − L % k
 问题转为求: (L+f(L,k))/k ( ∑ L + ∑ f ( L , k ) ) / k
 第一部分就是k=1时的情况,第二部分求法是枚举每条边算贡献。
 对于边 u>v u − > v ,算 u u 左边各点 到 v右边各点的距离 modk m o d k 的和。
 处理 cnt[u][i] c n t [ u ] [ i ] 表示从根节点到 u u 的子树节点距离modk等于 i i 的点的个数。
ans+=needu,vcnt[u][i]cnt[v][j]i[0,k1],j[0,k1]
 本题结束。

AC_Code:
#include<bits/stdc++.h>
#define lowbit(x) (x&(-(x)))
#define mme(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int MXN = 2e5 + 7;
const int MXE = 1e6 + 7;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;

int n, k;
vector<int> g[MXN];
LL sum[MXN], cnt[MXN][5] , ans;
void exe(int u,int Fa,int dd){
  sum[u] = cnt[u][dd%k] =1;
  for(int i=0;i<g[u].size();++i){
    int v=g[u][i];
    if(Fa==v)continue;
    exe(v,u,dd+1);
    sum[u]+=sum[v];
    ans += sum[v]*(n-sum[v]);
    for(int i = 0; i < k; ++i){
      for(int j = 0; j < k; ++j){
        LL tmp = ((i+j-2*dd)%k+k)%k;
        tmp = ((k-tmp)%k+k)%k;
        ans += tmp*cnt[u][i]*cnt[v][j];
      }
    }
    for(int i = 0; i < k; ++i)cnt[u][i]+=cnt[v][i];
  }
}
int main(){
  while(~scanf("%d%d", &n, &k)){
    memset(sum,0,sizeof(sum));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;++i)g[i].clear();
    for(int i=1,x,y;i<=n-1;++i){
      scanf("%d%d",&x,&y);
      g[x].push_back(y);
      g[y].push_back(x);
    }
    ans = 0;
    exe(1,-1,0);
    printf("%lld\n", ans/k);
  }
  return 0;
}


Problem Description:

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值