逆元链接:https://www.cnblogs.com/zzqc/p/7192436.html

经典的树分治题

#pragma comment("linker,"/STACK:102400000,102400000)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define mod 1000003
typedef long long ll
struct E{
int v,d,next;
E(){}
E(int vv,int nn):v(vv),next(nn){}
}e[MAXN<<];
bool vis[MAXN];
int size,head[MAXN],ans[];//边和答案
int flag[mod],F[mod],id[MAXN];//哈希
ll ni[mod];//1-mod之间的逆元表
int sum[MAXN],mi,cr;//cr是子树的路径数量
ll val[MAXN],path[MAXN];//点权路径
void init(){
size=;
memset(vis,,sizeof vis);
memset(ans,-,sizeof ans);
memset(head,-,sizeof head);
memset(flag,,sizeof flag);
}
void add(int u,int v){
e[size]=E(v,head[u]);
head[u]=size++;
}
//这个函数找路径
void dfs(int u,ll k){
int i,v;
sum[u]=;
vis[u]=true;
id[cr]=u;
path[cr++]=k*val[u]%mod;
ll tmp=path[cr-];
for(i=head[u];i!=-;i=e[i].next){
v=e[i].v;
if(vis[v]) continue;
dfs(v,tm);
sum[u]+=sum[v];
}
vis[u]=false;
}
ll k;
int n,ca;
void getans(int a,int b){
if(a>b) swap(a,b);
if(ans[]==- || ans[]>a)
ans[]=a,ans[]=b;
else if(ans[]==a && ans[]>b)
ans[]=b;
}
//找重心
void getroot(int u){
int i,v,mx=;
sum[u]=;
vis[u]=true;
for(i=head[u];i!=-;i=e[i].next){
v=e[i].v;
if(vis[v]) continue;
getroot(v);
sum[u]+=sum[v];
mx=max(mx,sum[v]);
}
mx=max(mx,sum[]-sum[u]);
if(mx<mi) mi=mx,root=u;
vis[u]=false;
}
void cal(int u,int cnt){
if(cnt==) return;
int i,v,j;
mi=n;
sum[]=cnt;//树规模为cnt
getroot(u);
vis[root]=true;
for(i=head[root];i~=-;i=e[i].next){
v=e[i].v;
if(vis[v]) continue;
cr=;
dfs(v,);
for(j=;j<cr;j++){
if(path[j]*val[root]%mod==k)//直接从根出发
getans(root,id[j]);
ll tmp=k*ni[path[j]*val[root]%mod]%mod;//k*x逆元=y
if(flag[tmp]!=ca) continue;//没有在当前树中找到路径
getans(F[tmp],id[j]);//F[tmp]是值为tmp的path对应的终点编号,id[j]是当前路径的终点编号
}
//把当前子树更新到目前哈希表中
for(j=;j<cr;j++){
int tmp=path[j];
if(flag[tmp]!=ca || F[tmp]>id[j])//如果当前哈希表状态中没有path[j],或者F[tmp]的结点编号没有优化到最小
F[tm]=id[j],flag[tm]=ca;
}
}
ca++;//每次搜完一颗子树,颜色数+1
//这里就是分治
for(i=head[root];i!=-;i=e[i].next){
if(vis[e[i].v])
continue;
cal(e[i].v,sum[e[i].v]);
}
}
//拓展欧几里得打表,求的逆元就是最后的x
ll egcd(ll a,ll b,ll &x,ll &y){
ll temp,tempx;
if(b==){
x=;y=;
return a;
}
temp=egcd(b,a%b,x,y);
tempx=x;
x=y;
y=tempx-a/b*y;
return temp;
}
int main(){
int u,v,i,j;
ll y;
for(i=;i<mod;i++){//拓展欧几里得打表求逆元,也可以递推打表,快速幂打表
egcd(i*1ll,mod*1ll,ni[i],y);
ni[i]%=mod,ni[i]=(ni[i]+mod)%mod;
}
while(scanf("%d%lld",&n,&k)==){
init();
ca=;//不能是0
for(i=;i<=n;i++) scanf("%lld",&val[i]);
for(i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
cal(,n);
if(ans[]==-)
puts("No solution");
else
printf("%d %d\n",ans[],ans[]);
}
}

最新文章

  1. sh6.脚本磁盘分区格式化
  2. Network Alignment(网络比对)模型
  3. SonarQube的使用入门
  4. Solved: Qt Library LNK 2001 staticMetaObject error
  5. C_中使用SendMessage
  6. 【转载】利用shell脚本获取一个文件的绝对路径readlink
  7. Linked List Cycle II
  8. Intel HD4000的驱动-黑苹果之路
  9. Linux Kernel 整数溢出漏洞
  10. [转]PB 基本语句 循环语句
  11. python爬虫下载文件
  12. [jdoj1817]Drainage Ditches_网络流
  13. 关于int main( int argc, char* argv[] ) 中arg和argv参数的解析及调试
  14. JavaScript中的this所引用的对象和如何改变这个引用
  15. K2 BPM获评“表现强劲”_2019 Forrester 报告_全球领先的工作流引擎
  16. eclipse与visualVM与mat
  17. Class对象、反射机制、获取Constructor构造方法
  18. [视频]K8飞刀 ms15022 office漏洞演示动画
  19. as 打包报错
  20. git的权威指南

热门文章

  1. location的三种连接方式和区别
  2. excel自动化翻译2
  3. JavaSE学习总结(十八)—— 多线程
  4. CM记录-优化配置解决Reduce卡顿问题
  5. 如何用matplotlib绘制决策边界
  6. fffmgg
  7. python - 装饰器+描述符(给类添加属性且属性类型审核)
  8. Django学习手册 - 模板语言(前端获取后台数据)
  9. jquery选择器最后一个,倒数第二个元素
  10. 20165230田坤烨《网络对抗》Exp1 PC平台逆向破解