[hdu4812]D Tree(点分治)
题意:问有多少条路径,符合路径上所有节点的权值乘积模1000003等于k。
解题关键:预处理阶乘逆元,然后通过hash和树形dp$O(1)$的判定乘积存在问题,注意此道题是如何处理路径保证不重复的,具有启发意义。
代码:2340ms,这段代码最重要的可取点就是如何通过操作省去memset的过程
复杂度:$O(n\log n)$
#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#define maxn 100040
#define maxm 1000500
using namespace std;
typedef long long ll;
const ll mod=;
const ll inf=1ll<<;
ll n,k,ans,size,s[maxn],f[maxn],path[maxn],cr,val[maxn],inv[maxm],ansl,ansr;
ll head[maxn],cnt,root,pathid[maxn],flag[maxm],mp[maxm],ca;
bool vis[maxn];
struct edge{
ll to,nxt;
}e[maxn<<]; void add_edge(ll u,ll v){
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
} inline ll read(){
char k=;char ls;ls=getchar();for(;ls<''||ls>'';k=ls,ls=getchar());
ll x=;for(;ls>=''&&ls<='';ls=getchar())x=(x<<)+(x<<)+ls-'';
if(k=='-')x=-x;return x;
} void get_root(ll u,ll fa){//get_root会用到size
s[u]=;f[u]=;//f是dp数组
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
get_root(v,u);
s[u]+=s[v];
f[u]=max(f[u],s[v]);
}
f[u]=max(f[u],size-s[u]);
root=f[root]>f[u]?u:root;
} void get_path_size(ll u,ll fa,ll dis){//同时获取size和depth,size是深度,depth是dis的意思
path[cr]=dis%mod*val[u]%mod;
pathid[cr]=u;
cr++;
s[u]=;
ll tm=path[cr-]%mod;
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
get_path_size(v,u,tm);
s[u]+=s[v];
}
} void getans(ll a,ll b){
if(a>b) swap(a,b);
if(ansl>a) ansl=a,ansr=b;
else if(ansl==a&&ansr>b) ansr=b;
} void work(ll u,ll fa){
vis[u]=true;
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
cr=;
get_path_size(v,u,);
for(ll j=;j<cr;j++){
if(path[j]*val[u]%mod==k) getans(pathid[j],u);
ll tm=k*inv[path[j]*val[u]%mod]%mod;
if(flag[tm]!=ca) continue;
getans(mp[tm],pathid[j]);
}
for(int j=;j<cr;j++){
ll tm=path[j];
if(flag[tm]!=ca||mp[tm]>pathid[j]) flag[tm]=ca,mp[tm]=pathid[j];
}
}
ca++;
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(vis[v]||v==fa) continue;
size=s[v],root=;
get_root(v,u);
work(root,u);
}
// vis[u]=false;
} void init(){
memset(vis,,sizeof vis);
memset(head,-,sizeof head);
//memset(flag,0,sizeof flag);
ans=cnt=;
//ca=1;
} ll mod_pow(ll x,ll n,ll p){
ll res=;
while(n){
if(n&) res=res*x%p;
x=x*x%p;
n>>=;
}
return res;
} int main(){
ll a,b;
f[]=inf;inv[]=;
for(ll i=;i<;i++) inv[i]=mod_pow(i,mod-,mod);
ca=;
while(scanf("%lld%lld",&n,&k)!=EOF){
ca++;
init();
for(int i=;i<=n;i++) val[i]=read()%mod;
for(int i=;i<n-;i++){
a=read(),b=read();
add_edge(a,b);
add_edge(b,a);
}
size=n,root=;
get_root(,-);
ansl=ansr=inf;
work(root,-);
if(ansl==inf) printf("No solution\n");
else printf("%lld %lld\n",ansl,ansr);
}
return ;
}
[hdu4812]D Tree(点分治)的更多相关文章
- HDU4812 D Tree(树的点分治)
题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所 ...
- HDU4812 D tree 【点分治 + 乘法逆元】
D树 时间限制:10000/5000 MS(Java / Others)内存限制:102400/102400 K(Java / Others) 总共提交5400个已接受的提交1144 问题描述 南京理 ...
- 【点分治】【乘法逆元】hdu4812 D Tree
思路比较裸,但是要把答案存到哈希表里面,这里需要一定技巧,否则会被K=1且点权全是1的数据卡飞.预处理乘法逆元.TLE了一天.换了种点分治的姿势…… #pragma comment(linker,&q ...
- 【BZOJ-1468】Tree 树分治
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 534[Submit][Status][Discuss] ...
- HDU 4812 D Tree 树分治+逆元处理
D Tree Problem Description There is a skyscraping tree standing on the playground of Nanjing Unive ...
- POJ 1741 Tree 树分治
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...
- [bzoj 1468][poj 1741]Tree [点分治]
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- 【CF434E】Furukawa Nagisa's Tree 点分治
[CF434E]Furukawa Nagisa's Tree 题意:一棵n个点的树,点有点权.定义$G(a,b)$表示:我们将树上从a走到b经过的点都拿出来,设这些点的点权分别为$z_0,z_1... ...
- POJ 1741 Tree(点分治点对<=k)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
随机推荐
- linux 打印系统时间操作
版权为个人所有,如需转载请说明出处.(东北大亨) http://www.cnblogs.com/northeastTycoon/p/5511498.html 1. 打开shell脚本 例子1:输出两天 ...
- SSIS
http://www.cnblogs.com/codefish/category/557802.html
- 五个知识体系之-SQL学习-第三天
1. sql约束作用 主键约束作用:保证插入数据的有效性.比如性别列,只能是“男”“女”,输入“abc”就是无效的,所以你可以添加约束alter table 表名add constraint chk_ ...
- Linux PPTP拨号
试验环境:Linux marsboard 3.4.90 #9 SMP PREEMPT Thu Mar 3 18:28:43 CST 2016 armv7l armv7l armv7l GNU/Linu ...
- API的理解和使用——有序集合
有序集合常用的命令 命令 功能 zadd key score member [score member ... ] 添加元素 zcard key 计算成员个数 zscore key member 计算 ...
- Machine Learning No.10: Anomaly detection
1. Algorithm 2. evaluating an anomaly detection system 3. anomaly detection vs supervised learning 4 ...
- (C)程序控制块(TCB)
程序控制块 1. 程序控制块 从代码上看,程序控制块就是一个结构体.例如: typedef struct tcb{ char * tast_name; //任务名字 int p; //任务重要级别 i ...
- Android NDK环境搭建
本文主要记录NDK环境在Ubuntu下的搭建. 下载NDK 在官网进行下载NDK https://developer.android.com/ndk/downloads/index.html 当前最新 ...
- 吴恩达机器学习笔记(七) —— K-means算法
主要内容: 一.K-means算法简介 二.算法过程 三.随机初始化 四.二分K-means 四.K的选择 一.K-means算法简介 1.K-means算法是一种无监督学习算法.所谓无监督式学习,就 ...
- TopCoder SRM420 Div1 RedIsGood —— 期望
题目链接:https://vjudge.net/problem/TopCoder-9915 (论文上的题) 题解: 更正:, i>0, j>0 代码如下: #include <ios ...