1. 程式人生 > >計蒜客 青雲的機房組網方案(莫比烏斯函式+樹上dsu)

計蒜客 青雲的機房組網方案(莫比烏斯函式+樹上dsu)

題意

給定一棵 n n 個節點的樹,每個節點上有一個點權,邊權為均 1 1 ,求所有點權互質的點對路徑總和。
1

n , 點權 100000 1 \leq n,\text{點權} \leq 100000

思路

對於一個數 a

a ,能與它產生貢獻的數和 a a 沒有公共質因子,那我們可以通過篩出莫比烏斯係數,就可以用容斥的方法求出與 a a 互質的部分了,如下圖:
在這裡插入圖片描述

A , B , C A,B,C a a 的三個質因子,與 a a 互質的部分就是上面的 U ( A B C ) U\setminus (A\bigcup B\bigcup C)
莫比烏斯係數篩法如下:

FOR(i,1,N)mo[i]=1,mark[i]=0;
FOR(i,2,N)if(!mark[i])
{
	for(int j=i;j<=N;j+=i)
	{
		mark[j]=1;
		if(j/i%i==0)mo[j]=0;
		else mo[j]=-mo[j];
	}
}

其中
μ ( x ) = {     1 if n is a square-free positive integer with an even number of prime factors 1 if n is a square-free positive integer with an odd number of prime factors     0 if n has a squared prime factor. \mu(x){}=\begin{cases} \ \ \ 1\quad \text{if n is a square-free positive integer with an even number of prime factors}\\ -1\quad \text{if n is a square-free positive integer with an odd number of prime factors}\\ \ \ \ 0\quad \text{if n has a squared prime factor.} \end{cases}
若一個數有一個因子是某個質數平方,那這個集合是某一個質數代表集合的子集,不會有貢獻計算。即一個數表示成若干個質數的幾次冪相乘時,這個冪次只能是 1 1 。除此外,有偶數個質因子的莫比烏斯函式值是 1 1 ,奇數個為 1 -1
那我們不妨列舉 LCA \text{LCA} ,計算每一個父節點中符合條件的子節點對的貢獻,單獨對某個因子而言,兩個同時是這個因子倍數的數將產生貢獻,乘上莫比烏斯係數再累和就是所有的貢獻。
貢獻的演算法只用化開式子即可,對於因子 s s ,某一個節點 u u ,給定所有節點的 l c a lca 時,對答案的貢獻就是 m o s v Dis ( v , u ) mo_s\displaystyle\sum_v\text{Dis}(v,u) ,其中 u , v u,v 屬於 l c a lca 不同子節點的子樹。
然後我們有 m o s v ( d e p u + d e p v 2 d e p l c a ) mo_s\displaystyle\sum_v(dep_u+dep_v-2dep_{lca})
s u m s sum_s 為目前全域性陣列中 s s 倍數的節點深度總和, c n t s cnt_s 為個數總和。
m o s ( s u m v + c n t s d e p u 2 c n t s d e p l c a ) mo_s(sum_v+cnt_sdep_u-2cnt_sdep_{lca})
維護好 s u m sum c n t cnt 陣列,每新增一棵子樹就計算一次貢獻即可。
把它改成 d s u dsu 複雜度就變成 O ( n log n ) O(n\log n) 了。

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
typedef long long LL;
using namespace std;
const int N=1e5+3;
template<const int maxn,const int maxm>struct Linked_list
{
    int head[maxn],to[maxm],nxt[maxm],tot;
    Linked_list(){clear();}
    void clear(){memset(head,-1,sizeof(head));tot=0;}
    void add(int u,int v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}
    #define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G;
Linked_list<N,N*64>fac;
int mo[N];bool mark[N];
int L[N],R[N],ori[N],ord,dep[N],fa[N],sz[N],son[N],a[N],n;
LL cnt[N],sum[N];
LL ans;
 
void init()
{
    FOR(i,1,N-3)mo[i]=1,mark[i]=0;
    FOR(i,2,N-3)if(!mark[i])
    {
        for(int j=i;j<=N-3;j+=i)
        {
            mark[j]=1;
            if(j/i%i==0)mo[j]=0;
            else mo[j]=-mo[j];
        }
    }
    FOR(i,1,N-3)if(mo[i])
        for(int j=i;j<=N-3;j+=i)
            fac.add(j,i);
    return;
}
 
void dfs(int u,int f,int d)
{
    dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0;
    L[u]=++ord,ori[ord]=u;
    EOR(i,G,u)
    {
        int v=G.to[i];
        if(v==f)continue;
        dfs(v,u,d+1);
        sz[u]+=sz[v];
        if(sz[v]>sz[son[u]])son[u]=v;
    }
    R[u]=ord;
}
 
void update(int l,int r,int k)
{
    FOR(i,l,r)
    {
        int u=ori[i];
        EOR(i,fac,a[u])
        {
            int s=fac.to[i];
            cnt[s]+=k;
            sum[s]+=k*dep[u];
        }
    }
}
void calc(int l,int r,int lca)
{
    FOR(i,l,r)
    {
        int u=ori[i];
        EOR(i,fac,a[u])
        {
            int s=fac.to[i];
            ans+=mo[s]*(sum[s]+cnt[s]*dep[u]-2*dep[lca]*cnt[s]);
        }
    }
}
 
void dsu(int u,int f)
{
    EOR(i,G,u)
    {
        int v=G.to[i];
        if(v==f||v==son[u])continue;
        
            
           

相關推薦

青雲機房組網方案函式+樹上dsu

題意 給定一棵 n n n 個節點的樹,每個節點上有一個點權,邊權為均

BZOJ 2440 完全平方數函式+容斥

   注意的兩點是二分的時候注意,要選取最小的那個答案,因為19是13個,20也是13個,而很明顯19才是符合答案的。 還有感覺題目給的資料範圍不對,實際比較大,所以二分的時候r大點。 #include<bits/stdc++.h> using nam

hdu6053 多校第二場函式,列舉

之前不知道莫比烏斯反演,看了一波,然後有些許理解,這個題其實就是使用了莫比烏斯函式U的定義,詳細的解題報告這裡說的比較清楚 #include<iostream> #include<cstdio> #include<cmath&

LCM(i,j)求和 函式

原題: BZOJ2693 題意: 求∑ni=1∑mj=1lcm(i,j)∑i=1n∑j=1mlcm(i,j) O(N)O(N)版本: 遇到lcm首先是換成gcd,Ans=∑ni=1∑mj=1i∗jgcd(i,j)Ans=∑i=1n∑j=1mi∗jg

BZOJ 3930 選數函式+杜教篩

#include<bits/stdc++.h> using namespace std; #define debug puts("YES"); #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #def

線性篩尤拉函式函式

在這裡提供三種線性篩的講解,它們分別是:素數篩,尤拉篩和莫比烏斯篩。 ·篩法正確性的重要理論依據: 上述函式均為積性函式。積性函式的性質為:若f(x)是一個積性函式,那麼對於任意素數a,b,滿足f(ab)=f(a)*f(b) ·一些可愛的要點(有助於理解篩法原理

我的第一道杜教篩函式求和 51Nod-1244

先總結一下,杜教篩的的精髓之處我認為在於通過兩個積性函式做狄利克雷卷積以後就可以對其進行整除分塊了,又因為一般用到杜教篩的題目資料量都特別大,是o(n)時間都跑不過來的資料,所以肯定不能預處理。但是這樣的題樣例數量不會太大,你只能每一次都計算結果,不能與處理出來結果,所以你需

HDU 6053 TrickGCD函式

題意:給出陣列 AA ,問有多個種 BB 陣列滿足所給條件。 思路 設 gcd(b1,...bn) = k (k >= 2),此時 k 對答案的貢獻為 (a1/k)*(a2/k)*(a3/k

LOJ #528. 「LibreOJ β Round #4」求和 函式

題意 計算 ∑i=1n∑j=1mμ2(gcd(i,j))∑i=1n∑j=1mμ2(gcd(i,j)) (mod(mod 998244353)998244353) 題解 ∑d=1nμ2(d)

HDU 1695 GCD 反演模板

GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 17212    Accepted

HDU6053 TrickGCD函式

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; /* 給定數列

HDU 6053 TrickGCD 函式

Description You are given an array A , and Zhu wants to know there are how many different array B

hdu3501 尤拉函式或容斥原理函式

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3501 題解1:顯然,本體可以用容斥原理,求出每個數的倍數情況,其係數就是莫比烏斯函式。 題解2:對於整

hdu 6134 函式,預處理快速求因子個數

> The Death Star, known officially as the DS-1 Orbital Battle Station, also known as the Death Star I, the First Death Star, Project Stardust internally

BZOJ 2301: [HAOI2011]Problem b反演

計算 algo cto ref blog image get txt += http://www.lydsy.com/JudgeOnline/problem.php?id=2301 題意:對於給出的n個詢問,每次求有多少個數對(x,y),滿足a≤x≤b,c&l

SPOJ - PGCD Primes in GCD Table反演

cnblogs -s def problems 前綴和 ret mage () eof http://www.spoj.com/problems/PGCD/en/ 題意: 給出a,b區間,求該區間內滿足gcd(x,y)=質數的個數。 思路: 設f(n)為 gc

hdu 1695 GCD入門

技術分享 sin urn cas str 由於 ons pre () 題意:求a<=x<=b ,x<=y<=d,中gcd(x,y)==k的數對個數 思路:題目可以轉化成求1<=x<=b/k,1<=y<=d/k中gcd(x,y)

數論18——反演定理反演

技術分享 滿足 urn spa isp name 角速度 我們 組成 莫比烏斯反演也是反演定理的一種 既然我們已經學了二項式反演定理 那莫比烏斯反演定理與二項式反演定理一樣,不求甚解,只求會用 莫比烏斯反演長下面這個樣子(=?ω?=) d|n,表示

【HDU1695】GCD反演

重復 min put clas 題解 iostream fine har clu 【HDU1695】GCD(莫比烏斯反演) 題面 題目大意 求\(a<=x<=b,c<=y<=d\) 且\(gcd(x,y)=k\)的無序數對的個數 其中,你可以假定\(

【Luogu3455】【POI2007】ZAP-Queries反演

stream bre 似的 string 獲得 計算 getc ans contain 【Luogu3455】【POI2007】ZAP-Queries(莫比烏斯反演) 題面 題目描述 FGD正在破解一段密碼,他需要回答很多類似的問題:對於給定的整數a,b和d,有多少正整數對