【BZOJ3451】Normal【期望线性性】【点分治】【NTT卷积】
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ3451】Normal【期望线性性】【点分治】【NTT卷积】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:隨機分治中心點分治的期望操作次數
n≤3×104n\leq 3\times 10^4n≤3×104
即求點分樹的 siz 之和的期望
即祖孫關系對數期望
考慮一有序點對 (u,v)(u,v)(u,v),uuu 在點分樹上是 vvv 祖先當且僅當 uuu 是 u~vu\sim vu~v 路徑上第一個被選為分治中心的,并且選擇路徑外的點是不影響的,所以概率為 1dist?(u,v)+1\dfrac 1{\operatorname{dist}(u,v)+1}dist(u,v)+11?
由期望線性性,答案為
∑i=1n∑j=1n1dist?(i,j)+1\sum_{i=1}^n\sum_{j=1}^{n}\frac 1{\operatorname{dist}(i,j)+1}i=1∑n?j=1∑n?dist(i,j)+11?
相當于是求距離為 0~n?10\sim n-10~n?1 的點對數量,考慮點分治
計算當前答案時發現是個卷積形式,使用 NTT 優化
算出整個連通塊的答案,然后容斥掉在同一個子樹中的
因為深度是不會超過大小的,所以復雜度為 O(nlog?2n)O(n\log ^2n)O(nlog2n)
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> #define MAXN 65536 using namespace std; const int MOD=998244353; inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;} inline int dec(const int& x,const int& y){return x<y? x-y+MOD:x-y;} typedef long long ll; inline int qpow(int a,int p) {int ans=1;while (p){if (p&1) ans=(ll)ans*a%MOD;a=(ll)a*a%MOD,p>>=1;}return ans; } #define inv(x) qpow(x,MOD-2) int rt[2][24]; int l,lim,r[MAXN]; inline void init(){lim=1<<l;for (int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));} inline void NTT(int* a,int type) {for (int i=0;i<lim;i++) if (i<r[i]) swap(a[i],a[r[i]]);for (int L=0;L<l;L++){int mid=1<<L,len=mid<<1;ll Wn=rt[type][L+1];for (int s=0;s<lim;s+=len)for (int k=0,w=1;k<mid;k++,w=w*Wn%MOD){int x=a[s+k],y=(ll)w*a[s+mid+k]%MOD;a[s+k]=add(x,y),a[s+mid+k]=dec(x,y);}}if (type){int t=inv(lim);for (int i=0;i<lim;i++) a[i]=(ll)a[i]*t%MOD;} } inline double calc(int* a,int n) {double ans=0;for (l=0;(1<<l)<=(n<<1);++l);init(),NTT(a,0);for (int i=0;i<lim;i++) a[i]=(ll)a[i]*a[i]%MOD;NTT(a,1);for (int i=0;i<lim;i++){ans+=(double)a[i]/(i+1);a[i]=0;}return ans; } vector<int> e[MAXN]; double ans; bool vis[MAXN]; int siz[MAXN],maxp[MAXN]={0x7fffffff},Rt; int a[MAXN]; void findrt(int u,int f,int sum) {siz[u]=1,maxp[u]=0;for (int i=0;i<(int)e[u].size();i++)if (e[u][i]!=f&&!vis[e[u][i]]){findrt(e[u][i],u,sum);siz[u]+=siz[e[u][i]];maxp[u]=max(maxp[u],siz[e[u][i]]);}maxp[u]=max(maxp[u],sum-siz[u]);if (maxp[u]<maxp[Rt]) Rt=u; } int dfs(int u,int f,int dep) {siz[u]=1,++a[dep];int mx=dep;for (int i=0;i<(int)e[u].size();i++)if (e[u][i]!=f&&!vis[e[u][i]]){mx=max(mx,dfs(e[u][i],u,dep+1));siz[u]+=siz[e[u][i]];}return mx; } inline void calc() {ans+=calc(a,dfs(Rt,0,0));for (int i=0;i<(int)e[Rt].size();i++)if (!vis[e[Rt][i]])ans-=calc(a,dfs(e[Rt][i],0,1)); } void solve() {int u=Rt;vis[u]=1;calc();for (int i=0;i<(int)e[u].size();i++)if (!vis[e[u][i]]){int v=e[u][i];Rt=0,findrt(v,0,siz[v]);solve();} } int main() {rt[0][23]=qpow(3,119),rt[1][23]=inv(rt[0][23]);for (int i=22;i>=0;i--){rt[0][i]=(ll)rt[0][i+1]*rt[0][i+1]%MOD;rt[1][i]=(ll)rt[1][i+1]*rt[1][i+1]%MOD;}int n;scanf("%d",&n);for (int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);++u,++v;e[u].push_back(v),e[v].push_back(u);}findrt(1,0,n);solve();printf("%.4f\n",ans);return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【BZOJ3451】Normal【期望线性性】【点分治】【NTT卷积】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我把网页上传到了空间怎么查看我上传的网页
- 下一篇: 拼多多如何更改头像