【CF434E】Furukawa Nagisa's Tree

题意:一棵n个点的树,点有点权。定义$G(a,b)$表示:我们将树上从a走到b经过的点都拿出来,设这些点的点权分别为$z_0,z_1...z_{l-1}$,则$G(a,b)=z_0+z_1k^1+z_2k^2+...+z_{l-1}k^{l-1}$。如果$G(a,b)=X \mod Y$(保证Y是质数),则我们称(a,b)是好的,否则是坏的。现在想知道,有多少个三元组(a,b,c),满足(a,b),(b,c),(a,c)都是好的或者都是坏的?

$n\le 10^5,Y\le 10^9$

题解:由于一个点对要么是好的要么是坏的,所以我们可以枚举一下所有符合条件的3元组的情况。不过符合条件需要3条边都相同,那我们可以反过来,统计不合法的3元组的情况(一共$2^3-2$种情况)。经过观察我们发现,我们可以在 同时连接两种颜色的边 的那个点处统计贡献,即把三元组的贡献放到了点上。我们设$in_0(),in_1(i),out_0(i),out_1(i)$表示i有多少个好(坏)边连入(出),则一个点对答案的贡献就变成:

$2in_0(i)in_1(i)+2out_0(i)out_1(i)+in_0(i)out_1(i)+in_1(i)out_0(i)$

最后将答案/2即可。

所以现在我们只需要求:对于每个点,有多少好边连入(连出)。这个用点分治可以搞定,因为我们容易计算两个多项式连接起来的结果。本题我采用的是容斥式的点分治。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,cnt,tot,mn,rt;
ll X,Y,K,Ki,ans;
ll pw[maxn],pi[maxn],v[maxn],in1[maxn],in0[maxn],out1[maxn],out0[maxn];
int to[maxn<<1],nxt[maxn<<1],head[maxn],vis[maxn],siz[maxn];
struct node
{
ll x;
int y;
node() {}
node(ll a,int b) {x=a,y=b;}
bool operator < (const node &a) const {return x<a.x;}
}p[maxn],q[maxn];
inline int rd()
{
char gc=getchar(); int ret=0;
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret;
}
inline void add(int a,int b)
{
to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
}
inline ll pm(ll x,ll y)
{
ll z=1;
while(y)
{
if(y&1) z=z*x%Y;
x=x*x%Y,y>>=1;
}
return z;
}
void getrt(int x,int fa)
{
int i,tmp=0;
siz[x]=1;
for(i=head[x];i!=-1;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) getrt(to[i],x),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);
tmp=max(tmp,n-siz[x]);
if(tmp<mn) mn=tmp,rt=x;
}
void getp(int x,int fa,int dep,ll s1,ll s2)
{
s1=(s1*K+v[x])%Y,s2=(s2+v[x]*((!dep)?0:pw[dep-1]))%Y,dep++;
p[++tot]=node((X-s1+Y)*pi[dep]%Y,x),q[tot]=node(s2,x);
for(int i=head[x];i!=-1;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa)
getp(to[i],x,dep,s1,s2);
}
void calc(int x,int flag,int dep,ll s1,ll s2)
{
int i,j,cnt;
tot=0;
s1=(s1*K+v[x])%Y,s2=(s2+v[x]*((!dep)?0:pw[dep-1]))%Y,dep++;
p[++tot]=node((X-s1+Y)*pi[dep]%Y,x),q[tot]=node(s2,x);
for(i=head[x];i!=-1;i=nxt[i]) if(!vis[to[i]]) getp(to[i],x,dep,s1,s2);
sort(p+1,p+tot+1),sort(q+1,q+tot+1);
for(cnt=0,i=j=1;i<=tot;i++)
{
for(;j<=tot&&q[j].x<=p[i].x;j++)
{
if(j==1||q[j].x!=q[j-1].x) cnt=0;
cnt++;
}
if(j!=1&&q[j-1].x==p[i].x) out1[p[i].y]+=cnt*flag;
}
for(cnt=0,i=j=1;i<=tot;i++)
{
for(;j<=tot&&p[j].x<=q[i].x;j++)
{
if(j==1||p[j].x!=p[j-1].x) cnt=0;
cnt++;
}
if(j!=1&&p[j-1].x==q[i].x) in1[q[i].y]+=cnt*flag;
}
}
void dfs(int x)
{
vis[x]=1;
int i;
calc(x,1,0,0,0);
for(i=head[x];i!=-1;i=nxt[i]) if(!vis[to[i]])
{
calc(to[i],-1,1,v[x],0);
tot=siz[to[i]],mn=1<<30,getrt(to[i],x),dfs(rt);
}
}
int main()
{
//freopen("cf434E.in","r",stdin); n=rd(),Y=rd(),K=rd(),X=rd(),Ki=pm(K,Y-2);
int i,a,b;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++) v[i]=rd();
for(i=pw[0]=pi[0]=1;i<=n;i++) pw[i]=pw[i-1]*K%Y,pi[i]=pi[i-1]*Ki%Y;
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
tot=n,mn=1<<30,getrt(1,0),dfs(rt);
for(i=1;i<=n;i++)
{
in0[i]=n-in1[i],out0[i]=n-out1[i];
ans+=2*in1[i]*in0[i]+2*out1[i]*out0[i]+in0[i]*out1[i]+in1[i]*out0[i];
}
printf("%lld",1ll*n*n*n-ans/2);
return 0;
}

【CF434E】Furukawa Nagisa's Tree 点分治的更多相关文章

  1. Codeforces 434E - Furukawa Nagisa's Tree(三元环+点分治)

    Codeforces 题面传送门 & 洛谷题面传送门 场号 hopping,刚好是我的学号(指 round 的编号) 注:下文中分别用 \(X,Y,K\) 代替题目中的 \(x,y,k\) 注 ...

  2. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

  3. HDU 4812 D Tree 树分治+逆元处理

    D Tree Problem Description   There is a skyscraping tree standing on the playground of Nanjing Unive ...

  4. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

  5. [bzoj 1468][poj 1741]Tree [点分治]

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

  6. POJ 1741 Tree(点分治点对<=k)

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

  7. POJ 1741.Tree 树分治 树形dp 树上点对

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 24258   Accepted: 8062 Description ...

  8. poj 1744 tree 树分治

    Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each ed ...

  9. CF1039D You Are Given a Tree 根号分治,贪心

    CF1039D You Are Given a Tree LG传送门 根号分治好题. 这题可以整体二分,但我太菜了,不会. 根号分治怎么考虑呢?先想想\(n^2\)暴力吧.对于每一个要求的\(k\), ...

随机推荐

  1. 安装 VS2017 的正确姿势

    自从装了长城带宽,我的肠子就变成青色的了. 国内的网络环境,真的是有很大的不同,有的人装 VS 的时候,号称满速,有的人(其实就是我)要等它下载很久,还告诉我有个组件没有安装成功.很久很久以前,VS ...

  2. IO流(2)—知识结构

    结构: 注:此IO包下主要介绍: 节点流:(字节流)FileInputStream.FileOutputStream.(字符流)Filereader.FileWriter 处理流(缓冲流):(字节流) ...

  3. Elasticsearch冷热集群搭建

    ES版本:6.2.4 集群环境:7台机器,每台部署一个master节点.其中3台部署2个hot节点,另外4台部署2个warm节点.共21个节点. 1. 挂盘 按实际情况分盘,一个机子上的2个data节 ...

  4. space.php

    天云信息技术有限公司 | 苏ICP备16033617号 1 0.275 ms SELECT * FROM uchome_session WHERE uid='1' Explain id select_ ...

  5. HashMap代码解析

    hashmap (jdk 1.7)使用 “数组-链表” 方式进行存储,图形化表示如下: 即,前面是一个数组,后面跟一个链表,那么数据结构这个对应到HashMap的代码里面是什么样子的呢? 在HashM ...

  6. python接口自动化测试(六)-unittest-单个用例管理

    前面五节主要介绍了环境搭建和requests库的使用,可以使用这些进行接口请求的发送.但是如何管理接口案例?返回结果如何自动校验?这些内容光靠上面五节是不行的,因此从本节开始我们引入python单元测 ...

  7. SpringBoot之整合Redis分析和实现-基于Spring Boot2.0.2版本

    背景介绍 公司最近的新项目在进行技术框架升级,基于的Spring Boot的版本是2.0.2,整合Redis数据库.网上基于2.X版本的整个Redis少之又少,中间踩了不少坑,特此把整合过程记录,以供 ...

  8. Python 3安装MySQLdb

    Python 2安装的是mysql-python,Python 3安装mysql-python以后,仍然不能import MySQLdb,原来Python 3应该安装mysqlclient,就可以im ...

  9. Deep Learning.ai学习笔记_第五门课_序列模型

    目录 第一周 循环序列模型 第二周 自然语言处理与词嵌入 第三周 序列模型和注意力机制 第一周 循环序列模型 在进行语音识别时,给定一个输入音频片段X,并要求输出对应的文字记录Y,这个例子中输入和输出 ...

  10. 构建自己的 Smart Life 私有云(一)-> 破解涂鸦智能插座

    博客搬迁至https://blog.wangjiegulu.com RSS订阅:https://blog.wangjiegulu.com/feed.xml 原文链接:https://blog.wang ...