圣诞树
来源:互联网 发布:mac登录掌上大学 编辑:程序博客网 时间:2024/04/28 13:41
题目描述
圣诞节到了,小可可送给小薰一棵圣诞树。这棵圣诞树很奇怪,它是一棵多叉树,有n个点,n-1条边。它的每个结点都有一个权值。小可可和小薰想用这棵树玩一个游戏。
定义(s,e)为树上从s到e的简单路径,我们可以记下在这条路径上经过的结点,定义这个结点序列为S(s,e)。
我们按照如下方法定义这个序列S(s,e)的权值G(S(s,e)):假设这个序列中结点的权值为Z0,Z1,…,Z(L-1),其中L为序列的长度,我们定义G(S(s,e))=Z0 × k0 + Z1 × k1 + … + Z(L-1) × k(L-1)。
如果路径(s,e)满足G(S(s,e)) ≡ x (mod y) ,那么这条路径属于小可可,否则这条路径属于小薰。小可可和小薰很显然不希望这个游戏变得那么简单。小薰认为如果路径(p1,p2)和(p2,p3)都属于他,那么路径(p1,p3)也属于他,反之如果路径(p1,p2)和(p2,p3)都属于小可可,那么路径(p1,p3)也属于小可可。然而这个性质并不总是正确的。所以小薰想知道到底有多少三元组(p1,p2,p3)满足这个性质。
小薰表示她看一眼就知道这道题怎么做了。你会吗?
输入
第一行包含四个整数n,y,k和x,其中n为圣诞树的结点数,y,k和x的含义如题目所示,题目保证y是一个质数。
第二行包含n个整数,第i个整数vi表示第i个结点的权值。
接下来n-1行,每行包含2个整数,表示树上的一条边。树的结点从1到n编号。
输出
包含一个整数,表示有多少整数组(p1,p2,p3)满足题目描述的性质。
样例输入
1 2 1 0
1
样例输出
1
提示
【样例2】
tree.in
tree.out
3 5 2 1
4 3 1
1 2
2 3
14
【样例3】
tree.in
tree.out
8 13 8 12
0 12 7 4 12 0 8 12
1 8
8 4
4 6
6 2
2 3
8 5
2 7
341
【数据规模】
对于20%的数据,n ≤ 200;
对于50%的数据,n ≤ 104;
对于100%的数据,1 ≤ n ≤ 105,2 ≤ y ≤ 109,1 ≤ k ≤ y,0 ≤ x < y。
题解
代码(能开long long 的就开long long 吧)
#include<bits/stdc++.h>#define ll long long#define N 100005using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}int cnt,rt,tot,sum;ll x,y,k,n;int Head[N],ret[2*N],Next[2*N];int val[N];int size[N],mx[N],bl[N];ll in[N],out[N],fac[N],inv[N];struct node{ll v;int id;}qg[N],qh[N];bool flag[N];bool cmp(node a,node b){return a.v<b.v;}ll gpow(ll x,ll k){ if (k==0) return 1; if (k==1) return x; ll t=gpow(x,k>>1); t=t*t%y; if (k&1) t=t*x%y; return t;}void pre(){ fac[0]=1; for (int i=1;i<=n;i++)fac[i]=(ll)fac[i-1]*k%y; inv[n]=gpow(fac[n],y-2); for (int i=n-1;i;i--)inv[i]=(ll)inv[i+1]*k%y;}inline void ins(int u,int v){ret[++tot]=v;Next[tot]=Head[u];Head[u]=tot;}void getroot(int u,int f)//找重心{ size[u]=1;mx[u]=0; for (int i=Head[u];i;i=Next[i]) { int v=ret[i]; if (!flag[v]&&v!=f) { getroot(v,u); size[u]+=size[v]; mx[u]=max(mx[u],size[v]); } } mx[u]=max(mx[u],sum-size[u]); if (mx[u]<mx[rt]) rt=u;}void dfs(int u,int f,ll h,ll g,int l)//搜索子数,h表示h(x,y),g表示g(x,y),l表示深度{ qh[++cnt].v=h;qg[cnt].v=(((ll)(x-g)%y+y)%y)*inv[l]%y; qh[cnt].id=u;qg[cnt].id=u;if (f==rt||u==rt) bl[u]=u;else bl[u]=bl[f]; for (int i=Head[u];i;i=Next[i]) { int v=ret[i]; if (v!=f&&!flag[v]) dfs(v,u,(h+val[v]*fac[l-1])%y,(g*k+val[v])%y,l+1); }}int queryr(int v)//二分相等的最右端{ int l=1,r=cnt; while (l!=r) { int mid=(l+r+1)>>1; if (qg[mid].v>v) r=mid-1;else l=mid; } return l;}int queryl(int v)//二分相等的最左端{ int l=1,r=cnt; while (l!=r) { int mid=(l+r)>>1; if (qg[mid].v<v) l=mid+1;else r=mid; } return l;}void solve(int u){ cnt=0;flag[u]=1; dfs(u,0,0,val[u],1); sort(qh+1,qh+cnt+1,cmp); sort(qg+1,qg+cnt+1,cmp); for (int i=1;i<=cnt;i++) { int l=queryl(qh[i].v); int r=queryr(qh[i].v); if (qg[l].v!=qh[i].v) continue; for (int j=l;j<=r;j++) if (bl[qh[i].id]!=bl[qg[j].id]||(bl[qh[i].id]==rt&&bl[qg[j].id]==rt)) { in[qh[i].id]++; out[qg[j].id]++; } }//更新in[]和out[] for (int i=Head[u];i;i=Next[i]) { int v=ret[i]; if (!flag[v]) { rt=0;sum=size[v]; getroot(v,0); solve(rt); } }}int main(){ n=read(),y=read(),k=read(),x=read(); pre(); for (int i=1;i<=n;i++) val[i]=read(); for (int i=1;i<n;i++) { int u=read(),v=read(); ins(u,v);ins(v,u); } rt=0;sum=n;mx[0]=n; getroot(1,0); solve(rt); ll ans=0; for (int i=1; i<=n; i++) ans+=((ll)in[i]*(n-out[i])+(ll)out[i]*(n-in[i])+(ll)2*out[i]*(n-out[i])+(ll)2*in[i]*(n-in[i]));//,cout<<i<<" "<<in[i]<<" "<<out[i]<<endl; cout<<(ll)n*n*n-ans/2<<endl;}
- 圣诞树
- 圣诞树
- 圣诞树
- 圣诞树
- 打印圣诞树
- 圣诞树2
- 【u228】圣诞树
- 为什么要查“圣诞树”
- 【搜索】【RQNOJ】圣诞树
- HTML5实现圣诞树效果
- 【最长路】圣诞树
- ZJUT 1153 圣诞树
- RQNOJ 172 圣诞树
- 【DFS】rqnoj P172 圣诞树
- 仿真树:仿真圣诞树
- 圣诞树成长历程(2)
- HTML&CSS--圣诞树
- PID172 / 圣诞树(RQNOJ)
- [LeetCode] 53. Maximum Subarray
- 中国大数据可视化展示系统应用端全球领先
- 《奔跑吧Linux内核》样章7月最强集合
- Android Studio 出现 Gradle's dependency cache may be corrupt 错误分析
- List以及arrayList,linkedlist,vector,以及stack的区别
- 圣诞树
- 嵌入式系统中boot的理解
- 企业微信付款接口
- Markdown编辑器插入EXCEL表格
- 第10章scroll家族
- 三种简单的html网页自动跳转方法
- 前端项目开发流程
- 在507干活的第4天(上)
- 请求转发(forward)和重定向(redirect)的区别