HDU 4812 D Tree 點分治 逆元

2021-07-25 05:22:08 字數 1497 閱讀 8261

題目要求在樹上找到一條鏈使得這條鏈上的點的乘積模mod等於k,求鏈首尾字典序最小的一條

看到題目就能知道是乙個點分治的題目,將樹按照重心分治之後,就是要統計以重心為根的子樹中,過樹根的mod為k的鏈字典序最小的一條,這裡的統計必需是在時間複雜度o(n) 以下才能過

**:

#pragma comment(linker,"/stack:102400000,102400000")

#include

using

namespace

std;

const

int maxn = 100000 + 50,mod = 1000000 + 3,inf = 0x3f3f3f3f;

typedef

long

long ll;

struct edgeedges[maxn * 2];

int head[maxn],tot;

void edge_init()

void insert_edge(int u,int v)

int n;

ll k;

ll node_value[maxn];

ll inv[mod];

int _hash[mod],flag[mod];

void init_inv()

int size[maxn],center,center_size;

int vis[maxn];

void getinfo(int rt,int fa)

}void getcenter(int rt,int fa,const

int tot_size)

if(tmp_size < center_size) center = rt,center_size = tmp_size;

}int ans_a,ans_b;

void update_ans(int a,int b)

ll path_value[maxn];

int path_value_node[maxn],path_cnt;

void solve_dfs(int rt,int fa,ll pre_value)

}int lable;

void solve(int rt)

for(int j = 0;j < path_cnt;++j)

}lable++;

for(i = head[rt];~i;i = edges[i].pre)

}int main()

memset(vis,0,sizeof vis);

memset(flag,0,sizeof flag);

ans_a = ans_b = inf;lable = 1;

solve(1);

if(ans_a != inf) printf("%d %d\n",ans_a,ans_b);

else

printf("no solution\n");

}return

0;}

樹的點分治 HDU4812 D Tree

題目傳送門 這次英語題應該比較好懂吧 大意是給定一棵有n nn個點的樹,每個點有權值v iv i vi 求是否存在一條路徑使得路徑上所有點的權值的乘積mod 106 3 bmod 10 6 3 mod106 3為k kk,輸出路徑首尾編號,若有多解輸出字典序最小的解。貌似很像不虛就是要ak?現在求路...

HDU4812 D Tree(樹的點分治)

題目大概說給一棵有點權的樹,輸出字典序最小的點對,使這兩點間路徑上點權的乘積模1000003的結果為k。樹的點分治搞了。因為是點權過根的兩條路徑的lca會被重複統計,而注意到1000003是質數,所以這個用乘法逆元搞一下就ok了。還有要注意 治 的各個實現,把時間複雜度 控制 在o nlogn wa...

hdu(1007) 最近點對 分治法

最近點對一般想到列舉 一一枚舉時間複雜度為n 2 列舉時候一些操作是多餘的,有了分治演算法的思想 把一些問題分個擊破,再回到整體。題目鏈結 以這道題為例,我們可以把他按照x軸的公升序分成多個子區域先在子區域中求最近點距離,然後將相鄰兩個子區域合併,看看兩個子區域中有沒有更小的。大致思想就是這樣的。設...