【codechef】 Prime Distance On Tree【求树上路经长度为i的路径条数】【点分治+FFT】

本文主要是介绍【codechef】 Prime Distance On Tree【求树上路经长度为i的路径条数】【点分治+FFT】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:【codechef】 Prime Distance On Tree

点分治+FFT水题……竟然n*n爆int没发现……
而且NTT TLE,FFT跑的超级快……

my  code:

#include <bits/stdc++.h>
using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 100005 ;
const int MAXE = 200005 ;
const double pi = acos ( -1.0 ) ;struct Complex {double r , i ;Complex () {}Complex ( double r , double i ) : r ( r ) , i ( i ) {}Complex operator + ( const Complex& t ) const {return Complex ( r + t.r , i + t.i ) ;}Complex operator - ( const Complex& t ) const {return Complex ( r - t.r , i - t.i ) ;}Complex operator * ( const Complex& t ) const {return Complex ( r * t.r - i * t.i , r * t.i + i * t.r ) ;}
} ;struct Edge {int v , n ;Edge () {}Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;Complex D[131072] ;
Edge E[MAXE] ;
int H[MAXN] , cntE ;int Q[MAXN] , head , tail ;
int dep[MAXN] ;
int pre[MAXN] ;
int siz[MAXN] ;
int cnt[MAXN] ;
int vis[MAXN] ;int pri[MAXN] ;
LL ans[MAXN] ;
int n ;void DFT ( Complex y[] , int n , int rev ) {for ( int i = 1 , j , k , t ; i < n ; ++ i ) {for ( j = 0 , k = n >> 1 , t = i ; k ; k >>= 1 , t >>= 1 ) {j = j << 1 | t & 1 ;}if ( i < j ) swap ( y[i] , y[j] ) ;}for ( int s = 2 , ds = 1 ; s <= n ; ds = s , s <<= 1 ) {Complex wn ( cos ( rev * 2 * pi / s ) , sin ( rev * 2 * pi / s ) ) ;for ( int k = 0 ; k < n ; k += s ) {Complex w ( 1 , 0 ) , t ;for ( int i = k ; i < k + ds ; ++ i , w = w * wn ) {y[i + ds] = y[i] - ( t = w * y[i + ds] ) ;y[i] = y[i] + t ;}}}
}void preprocess () {for ( int i = 2 ; i < MAXN ; ++ i ) pri[i] = 1 ;for ( int i = 2 ; i < MAXN ; ++ i ) if ( pri[i] ) {for ( int j = i + i ; j < MAXN ; j += i ) pri[j] = 0 ;}
}       void init () {cntE = 0 ;clr ( H , -1 ) ;clr ( vis , 0 ) ;clr ( ans , 0 ) ;
}void addedge ( int u , int v ) {E[cntE] = Edge ( v , H[u] ) ;H[u] = cntE ++ ;
}int get_root ( int s ) {head = tail = 0 ;Q[tail ++] = s ;pre[s] = 0 ;while ( head != tail ) {int u = Q[head ++] ;siz[u] = 1 ;cnt[u] = 0 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( v == pre[u] || vis[v] ) continue ;pre[v] = u ;Q[tail ++] = v ;}}int root = s , root_siz = tail ;while ( head ) {int u = Q[-- head] , p = pre[u] ;cnt[u] = max ( cnt[u] , tail - siz[u] ) ;if ( cnt[u] < root_siz ) {root = u ;root_siz = cnt[u] ;}siz[p] += siz[u] ;if ( siz[u] > cnt[p] ) cnt[p] = siz[u] ;}return root ;
}void calc ( int s , int init_dis , int f ) {head = tail = 0 ;Q[tail ++] = s ;dep[s] = init_dis ;pre[s] = 0 ;while ( head != tail ) {int u = Q[head ++] ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( vis[v] || v == pre[u] ) continue ;dep[v] = dep[u] + 1 ;pre[v] = u ;Q[tail ++] = v ;}}int n1 = 1 , len = ( dep[Q[tail - 1]] + 1 ) * 2 ;while ( n1 < len ) n1 <<= 1 ;for ( int i = 0 ; i < n1 ; ++ i ) D[i] = Complex ( 0.0 , 0.0 ) ;while ( head ) D[dep[Q[-- head]]].r += 1 ;DFT ( D , n1 , +1 ) ;for ( int i = 0 ; i < n1 ; ++ i ) D[i] = D[i] * D[i] ;DFT ( D , n1 , -1 ) ;for ( int i = 0 ; i < n1 ; ++ i ) D[i].r /= n1 ;int n2 = min ( n , n1 ) ;for ( int i = 1 ; i < n2 ; ++ i ) {LL tmp = ( LL ) ( D[i].r + 0.5 ) ;ans[i] += f ? tmp : -tmp ;}
}void dfs ( int u ) {int root = get_root ( u ) ;vis[root] = 1 ;calc ( root , 0 , 1 ) ;for ( int i = H[root] ; ~i ; i = E[i].n ) if ( !vis[E[i].v] ) calc ( E[i].v , 1 , 0 ) ;for ( int i = H[root] ; ~i ; i = E[i].n ) if ( !vis[E[i].v] ) dfs ( E[i].v ) ;
}void solve () {int u , v ;init () ;for ( int i = 1 ; i < n ; ++ i ) {scanf ( "%d%d" , &u , &v ) ;addedge ( u , v ) ;addedge ( v , u ) ;}dfs ( 1 ) ;LL res = 0 ;for ( int i = 2 ; i < n ; ++ i ) {if ( pri[i] ) res += ans[i] ;}printf ( "%.6f\n" , 1.0 * res / ( ( LL ) n * ( n - 1 ) ) ) ;
}int main () {preprocess () ;while ( ~scanf ( "%d" , &n ) ) solve () ;return 0 ;
}

这篇关于【codechef】 Prime Distance On Tree【求树上路经长度为i的路径条数】【点分治+FFT】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139176

相关文章

hdu2544(单源最短路径)

模板题: //题意:求1到n的最短路径,模板题#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#i

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

【408DS算法题】039进阶-判断图中路径是否存在

Index 题目分析实现总结 题目 对于给定的图G,设计函数实现判断G中是否含有从start结点到stop结点的路径。 分析实现 对于图的路径的存在性判断,有两种做法:(本文的实现均基于邻接矩阵存储方式的图) 1.图的BFS BFS的思路相对比较直观——从起始结点出发进行层次遍历,遍历过程中遇到结点i就表示存在路径start->i,故只需判断每个结点i是否就是stop

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

树(Tree)——《啊哈!算法》

树 什么是树?树是一种特殊的图,不包含回路的连通无向树。 正因为树有着“不包含回路”这个特点,所以树就被赋予了很多特性。 一棵树中的任意两个结点有且仅有唯一的一条路径连通。一棵树如果有n个结点,那么它一定恰好有n-1条边。在一棵树中加一条边将会构成一个回路。 一棵树有且只有一个根结点。 没有父结点的结点称为根结点(祖先)。没有子结点的结点称为叶结点。如果一个结点既不是根结点也不是叶

图的最短路径算法——《啊哈!算法》

图的实现方式 邻接矩阵法 int[][] map;// 图的邻接矩阵存储法map = new int[5][5];map[0] = new int[] {0, 1, 2, 3, 4};map[1] = new int[] {1, 0, 2, 6, 4};map[2] = new int[] {2, 999, 0, 3, 999};map[3] = new int[] {3, 7

vcpkg子包路径批量获取

获取vcpkg 子包的路径,并拼接为set(CMAKE_PREFIX_PATH “拼接路径” ) import osdef find_directories_with_subdirs(root_dir):# 构建根目录下的 "packages" 文件夹路径root_packages_dir = os.path.join(root_dir, "packages")# 如果 "packages"

226 Invert Binary Tree

//226 Invert Binary Tree//算法思路:主要使用递归算法public class Solution {public TreeNode invertTree(TreeNode root) {//1 出口 空节点if (root==null)return null;//2 递归 调用自己TreeNode left = root.left;TreeNode right = ro