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

D Tree

Problem Description

There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each branch can be treated as a vertex). Today the students under the tree are considering a problem: Can we find such a chain on the tree so that the multiplication of all integers on the chain (mod 106 + 3) equals to K?
Can you help them in solving this problem?

Input

There are several test cases, please process till EOF.
Each test case starts with a line containing two integers N(1 <= N <= 105) and K(0 <=K < 106 + 3). The following line contains n numbers vi(1 <= vi < 106 + 3), where vi indicates the integer on vertex i. Then follows N - 1 lines. Each line contains two integers x and y, representing an undirected edge between vertex x and vertex y.

Output

For each test case, print a single line containing two integers a and b (where a < b), representing the two endpoints of the chain. If multiply solutions exist, please print the lexicographically smallest one. In case no solution exists, print “No solution”(without quotes) instead.
For more information, please refer to the Sample Output below.

Sample Input

5 60
2 5 2 3 3
1 2
1 3
2 4
2 5
5 2
2 5 2 3 3
1 2
1 3
2 4
2 5

Sample Output

3 4
No solution

Hint

1. “please print the lexicographically smallest one.”是指: 先按照第一个数字的大小进行比较,若第一个数字大小相同,则按照第二个数字大小进行比较,依次类推。

2. 若出现栈溢出,推荐使用C++语言提交,并通过以下方式扩栈:
#pragma comment(linker,"/STACK:102400000,102400000")

题意:

  给你一棵树n个点,一个K

  让你找到一条 a->b 的字典数最小的 路径满足 这条路径 上点权 乘积取mod下 等于K

题解:

  预处理小于mod的 所有逆元

  树分治 即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;

#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair

typedef long long LL;
const long long INF = 1e18;
const double Pi = acos(-1.0);
const int N = 1e5+10, M = 1e6+11, inf = 2e9, mod = 1000003;

int head[N],vis[N],f[N],siz[N],id[N],n,t = 1,ansl,ansr,allnode,root;

struct edge{int to,next;}e[N * 4];
LL mp[M],inv[M],v[M],K,deep[M];
void add(int u,int v) {e[t].next=head[u];e[t].to=v;head[u]=t++;}

void getroot(int u,int fa) {
        f[u] = 0;
        siz[u] =  1;
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(vis[to] || to == fa) continue;
            getroot(to,u);
            siz[u] += siz[to];
            f[u] = max(f[u],siz[to]);
        }
        f[u] = max(f[u], allnode - siz[u]);
        if(f[u] < f[root]) root = u;
}
void getdeep(int u,int fa,LL now) {
    deep[++deep[0]] = now*v[u]%mod;
    id[deep[0]] = u;
    for(int i = head[u]; i; i = e[i].next) {
        int to = e[i].to;
        if(vis[to] || to == fa) continue;
        getdeep(to,u,now*v[u]%mod);
    }
}
void update(int u,int x,int y) {
        int tmp = mp[inv[x*v[u]%mod]*K%mod];
        if(!tmp) return ;
        if(y > tmp) swap(y,tmp);
        if(y < ansl || (y == ansl && tmp < ansr)) ansl = y, ansr = tmp;
}

void work(int u){
        vis[u] = 1;
        mp[1] = u;
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(vis[to]) continue;
            deep[0] = 0;
            getdeep(to,u,1);
            for(int j = 1; j <= deep[0]; ++j) update(u,deep[j],id[j]);
            for(int j = 1; j <= deep[0]; ++j) if(!mp[deep[j]] || mp[deep[j]] > id[j])mp[deep[j]] = id[j];
        }
        mp[1] = 0;
         for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(vis[to]) continue;
            deep[0] = 0;
            getdeep(to,u,1);
            for(int j = 1; j <= deep[0]; ++j)  mp[deep[j]] = 0;
        }
         for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(vis[to]) continue;
            root = 0;
            allnode = siz[to];
            getroot(e[i].to,root);
            work(root);
         }
}
int main() {
    inv[1]=1;
    for(int i=2;i<mod;i++){int a=mod/i,b=mod%i;inv[i]=(inv[b]*(-a)%mod+mod)%mod;}
    while(~scanf("%d%I64d",&n,&K)) {
        t = 1;memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        ansl = ansr = inf;
        for(int i = 1; i <= n; ++i) scanf("%I64d",&v[i]);
        for(int i = 1; i < n; ++i) {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        f[0]=inf;
        allnode=n;root=0;
        getroot(1,0);
        work(root);
        if(ansl == inf) puts("No solution");else
        printf("%d %d\n",ansl,ansr);
    }
    return 0;
}
时间: 2024-08-24 14:16:39

HDU 4812 D Tree 树分治+逆元处理的相关文章

HDU 4812 D Tree 树分治+逆元+hash新姿势

题意: 给定n个点的树 K 下面n个数是点权 下面n-1行给出树边. 问: 是否存在一条路径使得路径上点权积 % mod  = K 若存在则输出路径的两端. 若存在多条路径则输出字典序最小的一条. 思路: 按树重心分治. 分成路径是否经过树重心. 然后用力码.. has[x] = u; 表示乘积为x 对应的点是u 但这样has就不能用计数器来优化清空. 所以用2个数组: has[x] = cnt; has_id[x] = u; 这样has里存的是乘积为x是否存在.has_id[x] 来记录点.

hdu 4812 D Tree(树的点分治)

D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 1687    Accepted Submission(s): 263 Problem Description There is a skyscraping tree standing on the playground of Nanjing University of

HDU 4812 D Tree 树分区+逆+hash新位置

意甲冠军: 特定n点树 K 以下n号码是正确的点 以下n-1行给出了树的侧. 问: 所以,如果有在正确的道路点图的路径 % mod  = K 如果输出路径的两端存在. 多条路径则输出字典序最小的一条. 思路: 按树重心分治. 分成路径是否经过树重心. 然后用力码. . has[x] = u; 表示乘积为x 相应的点是u 但这样has就不能用计数器来优化清空. 所以用2个数组: has[x] = cnt; has_id[x] = u; 这样has里存的是乘积为x是否存在.has_id[x] 来记录

HDU 3333 Turing Tree 树状数组 离线查询

题意: 给你一个数列,然后有n个查询,问你给定区间中不同数字的和是多少. 思路还是比较难想的,起码对于蒟蒻我来说. 将区间按照先右端点,后左端点从小到大排序之后,对于每个查询,我只要维护每个数字出现的最后一次就可以了(这个结论稍微想一下就可以证明是正确的). 然后就是简单的点更新,区间求和问题了- #include <cstdio> #include <cstring> #include <iostream> #include <map> #include

HDU 4812 D Tree

Description There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each branch can be treat

poj 1744 tree 树分治

Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of ve

【BZOJ-1468】Tree 树分治

1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k Sample Input 7 1 6 13 6

【POJ1741】Tree 树分治 模板咯?

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44302921"); } 题意: 给你一棵无根树,求有多少点对之间距离<=K. 题解: 树分治. 然后对于一个重心X,我们把它的所有子树中的所有点存到结构体数组中. 结构体中存距离和子树编号. 第一遍sort,我们双指针扫哪些点

hdu 3333 Turing Tree (树状数组+离线处理+离散化)

Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3981    Accepted Submission(s): 1349 Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems a