传送门

本来想用点分治做,结果root又求不对 算的时候还算错了 我好菜啊

结果szr大佬告诉我是树形dp

我好菜啊!!

我们有$\lceil \frac{x}{k} \rceil = \frac{x+(k-x)\%k}{k}$

于是可以把这个拆成两部分来求,最后加在一起再除个k

距离和很好求,连接x和fa[x]的边的贡献就是$size[x]*(N-size[x])$

然后考虑到k很小,我们可以直接记x的子树中到x距离%k=y的个数f[x][y],然后拿这个去算

 #pragma GCC optimize(3)
#include<bits/stdc++.h>
#define pa pair<ll,ll>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=1e5+,maxk=; inline char gc(){
return getchar();
static const int maxs=<<;static char buf[maxs],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,maxs,stdin),p1==p2)?EOF:*p1++;
}
inline ll rd(){
ll x=;char c=gc();bool neg=;
while(c<''||c>''){if(c=='-') neg=;c=gc();}
while(c>=''&&c<='') x=(x<<)+(x<<)+c-'',c=gc();
return neg?(~x+):x;
} int eg[maxn*][],egh[maxn],ect=;
int N,K,siz[maxn],dcnt[maxk],smsiz,fa[maxn];
ll ans;
bool flag[maxn]; inline void adeg(int a,int b,int c){
eg[++ect][]=b,eg[ect][]=c,eg[ect][]=egh[a],egh[a]=ect;
} void getroot(int x,int f,int &rt,int &mis){
siz[x]=;
int mm=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f||flag[b]) continue;
fa[b]=x;getroot(b,x,rt,mis);
siz[x]+=siz[b];mm=max(mm,siz[b]);
}
mm=max(mm,smsiz-siz[x]);
if(mm<mis) rt=x,mis=mm;
} void getdis(int x,int f,int d){
dcnt[d]++;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f||flag[b]) continue;
getdis(b,x,(d+eg[i][])%K);
}
} inline ll calc(int x,int ini){
ll re=;
CLR(dcnt,);getdis(x,,ini);
for(int i=;i<K;i++){
for(int j=i+;j<K;j++){
re+=1ll*dcnt[i]*dcnt[j]*((K+(K-i-j)%K)%K);
}
}
for(int i=;i<K;i++) re+=1ll*dcnt[i]*(dcnt[i]-)/*((K+(K-i-i)%K)%K);
return re;
} void solve(int x){
flag[x]=;
ans+=calc(x,);
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(flag[b]) continue;
ans-=calc(b,eg[i][]%K);
int rt=,mis=1e9;smsiz=siz[b];
getroot(b,,rt,mis);
siz[fa[rt]]=smsiz-siz[rt];
solve(rt);
}
} void dfs(int x,int f){
siz[x]=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f) continue;
dfs(b,x);siz[x]+=siz[b];
ans+=1ll*siz[b]*(N-siz[b])*eg[i][];
}
} int main(){
// freopen("t3.in","r",stdin);
// freopen("t3.out","w",stdout);
int i,j,k;
N=rd(),K=rd();
for(i=;i<N;i++){
int a=rd(),b=rd(),c=rd();
adeg(a,b,c);adeg(b,a,c);
}
smsiz=N;int mis=1e9,rt=;
getroot(,,rt,mis);
solve(rt);
dfs(,);
printf("%lld\n",ans/K);
return ;
}

ZZ点分治

 #include<bits/stdc++.h>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int maxn=1e5+,maxk=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int eg[maxn*][],egh[maxn],ect;
int dp[maxn][maxk],siz[maxn];
int N,K;
ll ans; inline void adeg(int a,int b,int c){
eg[++ect][]=b,eg[ect][]=c,eg[ect][]=egh[a],egh[a]=ect;
} inline void dfs(int x,int f){
siz[x]=;dp[x][]=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];if(b==f) continue;
dfs(b,x);siz[x]+=siz[b];
ans+=1ll*eg[i][]*(N-siz[b])*siz[b];
for(int j=;j<K;j++)
for(int k=;k<K;k++)
ans+=1ll*((K+(-(j+eg[i][])%K-k)%K)%K)*dp[b][j]*dp[x][k];
for(int j=;j<K;j++)
dp[x][(j+eg[i][])%K]+=dp[b][j];
}
} int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd(),K=rd();
for(i=;i<N;i++){
int a=rd(),b=rd(),c=rd();
adeg(a,b,c);adeg(b,a,c);
}
dfs(,);
printf("%lld\n",ans/K);
return ;
}

noiac132 B君的第三题 (树形dp)的更多相关文章

  1. test20181016 B君的第三题

    题意 B 君的第三题(haskell) 题目描述 大学四年,我为什么,为什么不好好读书,没找到和你一样的工作. B 君某天看到了这样一个题,勾起了无穷的回忆. 输入\(n, k\) 和一棵\(n\) ...

  2. test20181015 B 君的第三题

    题意 B 君的第三题(zhengzhou) 题目描述 让你在战争和耻辱中做一块选择,你选择耻辱,可你将来还得进行战争. 在平面上有n 个整点(横纵坐标都是整数) B 君想找到一个整点,使得这个点,到所 ...

  3. test20181018 B君的第三题

    题意 B 君的第三题(shenyang) 题目描述 客似云来,万里无云 B 君得到了一个数组\(\{a_1,a_2,\dots,a_n\}\). B 君想通过修改让数组中个每对数都互质. 每次使一个数 ...

  4. test20181019 B君的第三题

    题意 B 君的第三题(urumqi) 题目描述 风雨如晦,鸡鸣不已. B 君最近在研究自己的学长都在做什么工作,每个学长属于一个公司. B 君会获得一些信息,比如x 和y 在相同公司,x 和y 在不同 ...

  5. POJ-3659-最小支配集裸题/树形dp

    Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7127   Accepted: 254 ...

  6. 加分二叉树 vijos1991 NOIP2003第三题 区间DP/树形DP/记忆化搜索

    描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一 ...

  7. HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)

    Terrorist’s destroy Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  8. 【uva1380 - 一个调度问题】思路题+树形dp

    [题意] 有n<=200个恰好需要一天完成的任务,要求用最少的时间完成所有任务.任务可以同时完成.但是有一些约束,分有向和无向两种,其中A-->B表示A必须在B前面完成,而A--B表示A和 ...

  9. 【DP_树形DP专题】题单总结

    转载自 http://blog.csdn.net/woshi250hua/article/details/7644959#t2 题单:http://vjudge.net/contest/123963# ...

随机推荐

  1. PV、TPS、QPS计算公式(转)

    英文解释: PV=page viewTPS=transactions per secondQPS=queries per secondRPS=requests per second RPS=并发数/平 ...

  2. 【Python3练习题 020】 求1+2!+3!+...+20!的和

    方法一 import functools   sum = 0 for i in range(1,21):     sum = sum + functools.reduce(lambda x,y: x* ...

  3. [转帖]Windows 10新预览版上线:可直接运行任意安卓APP了

    Windows 10新预览版上线:可直接运行任意安卓APP了 http://www.pcbeta.com/viewnews-80316-1.html 今晨(3月13日),微软面向Fast Ring(快 ...

  4. 【学亮IT手记】利用字节流复制图片

  5. pHP生成唯一单号

    这几天一直在写个人使用的用户中心,虽然期间遇到不少的问题,但还是一点点的都解决了,也从制作期间学到不少的知识,今天就说一说利用PHP生成订单单的方法. 订单号,大家都不陌生,无论从在网上购物,还是在线 ...

  6. 极验3.0滑动拼图验证的使用--java

    [ 前言: 在登录其他网站的时候,看到有个滑动拼图的验证觉得挺好玩的,以前做一个图片验证的小demo,现在发现很多网站都开始流行滑动拼图的验证了,今天也想自己动手来弄一个. 废话不多说,开始撸起来! ...

  7. C# Note30: 软件加密机制以及如何防止反编译

    参考文章: C#软件license管理(简单软件注册机制) 软件加密技术和注册机制 .NET中的许可证机制--License 背景 .net是一种建立在虚拟机上执行的语言,它直接生成 MSIL 的中间 ...

  8. dart正则

    1.前言 API中对于正则表达式的注释是:正则表达式的规范和语义与JavaScript相同详细的规范可以参考:http://ecma-international.org/ecma-262/5.1/#s ...

  9. hive 查询注意问题

    1)对于hive内置的列,不是自己建的,在查询的时候需要添加反引号` 比如:`_mt_message`,别在这里犯错误, (2)南京的_mt_message是json的格式,所以可以直接使用:get_ ...

  10. java & jdk

    java & jdk JDK 下载太慢 & java 12 https://download.oracle.com/otn-pub/java/jdk/12.0.1+12/69cfe15 ...