zoukankan      html  css  js  c++  java
  • CodeChef

    Prime Distance On Tree

    Problem description.

    You are given a tree. If we select 2 distinct nodes uniformly at random, what's the probability that the distance between these 2 nodes is a prime number?

    Input

    The first line contains a number N: the number of nodes in this tree.
    The following N-1 lines contain pairs a[i] and b[i], which means there is an edge with length 1 between a[i] and b[i].

    Output

    Output a real number denote the probability we want.
    You'll get accept if the difference between your answer and standard answer is no more than 10^-6.

    Constraints

    2 ≤ N ≤ 50,000

    The input must be a tree.

    Example

    Input:
    5
    1 2
    2 3
    3 4
    4 5
    
    Output:
    0.5
    

    Explanation

    We have C(5, 2) = 10 choices, and these 5 of them have a prime distance:

    1-3, 2-4, 3-5: 2

    1-4, 2-5: 3

    Note that 1 is not a prime number.

    题意:

        给你一颗树,n个点,n-1条边

        让你求任意选两个不同的点,其距离是素数的概率

    题解:

        点分治

        求出只经过重心的所有路径深度种类数

        让属于不同的子树的点,利用其深度进行任意组合(FFT加速)求出最后组合结果

        累积是素数的答案即可,复杂度 n* logn * logn

    #include<bits/stdc++.h>
    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;
    typedef unsigned long long ULL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 3e5+20, M = 1e6+10, mod = 1e9+7,inf = 2e9;
    
    
    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 ) ;
        }
    } ;
    
    void FFT ( Complex y[] , int n , int rev ) {
        for ( int i = 1 , j , t , k ; i < n ; ++ i ) {
            for ( j = 0 , t = i , k = n >> 1 ; 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 = Complex ( cos ( rev * 2 * pi / s ) , sin ( rev * 2 * pi / s ) ) , w ( 1 , 0 ) , t ;
            for ( int k = 0 ; k < ds ; ++ k , w = w * wn ) {
                for ( int i = k ; i < n ; i += s ) {
                    y[i + ds] = y[i] - ( t = w * y[i + ds] ) ;
                    y[i] = y[i] + t ;
                }
            }
        }
        if ( rev == -1 ) for ( int i = 0 ; i < n ; ++ i ) y[i].r /= n ;
    }
    Complex s[N],t[N];
    
    int vis[N],f[N],siz[N],n,allnode,root;
    int P[N];
    vector<int > G[N];
    void init() {
        for(int i = 2; i <= 2*n; ++i) {
            if(!P[i]) {
                for(int j = i+i; j <= 2*n; j += i)
                    P[j] = 1;
            }
        }
        P[1] = 1;
        for(int i = 1; i <= n; ++i) vis[i] = 0;
    }
    void getroot(int u,int fa) {
            f[u] = 0;
            siz[u] =  1;
            for(int i = 0; i < G[u].size(); ++i) {
                int to = G[u][i];
                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;
    }
    
    int len = 1,cnt[N],dep[N],nowcnt[N],mxdep;
    LL ans = 0;
    void getdeep(int u,int f) {
        siz[u] = 1;
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(vis[to] || to == f) continue;
            dep[to] = dep[u] + 1;
            getdeep(to,u);
            mxdep = max(mxdep,dep[to]);
            siz[u] += siz[to];
        }
    }
    void dfs(int u,int f,int p) {
        nowcnt[dep[u]]+=p;
        if(p == -1) cnt[dep[u]] += 1;
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(vis[to] || to == f) continue;
            dfs(to,u,p);
        }
    }
    LL cal(int u) {
        LL ret = 0;
        for(int i = 0; i <= n; ++i) cnt[i] = 0;
        cnt[0] = 1;
        dep[u] = 0;
        mxdep = -1;
        getdeep(u,0);
        len = 1;
        while(len <= 2*mxdep) len<<=1;
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(vis[to]) continue;
            dfs(to,u,1);
            for(int j = 0; j < len; ++j) t[j] = Complex(nowcnt[j],0);
            for(int j = 0; j < len; ++j) s[j] = Complex(cnt[j],0);
    
            FFT(s,len,1);FFT(t,len,1);
            for(int j = 0; j < len; ++j) s[j] = s[j] * t[j];
            FFT(s,len,-1);
            for(int j = 0;j < len; ++j) {
                LL tmp = (s[j].r+0.5);
    
                if(P[j]) continue;
    
                ret += tmp;
            }
            dfs(to,u,-1);
        }
        return ret;
    }
    void work(int u) {
        vis[u] = 1;
        ans += cal(u);
       // exit(0);
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(vis[to]) continue;
            allnode = siz[to];
            root = 0;
            getroot(to,0);
            work(root);
        }
    }
    int main() {
        scanf("%d",&n);
        while(len <= n) len<<=1;
        init();
        for(int i = 1; i < n; ++i) {
            int x,y;
            scanf("%d%d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
    
        ans = 0;
        f[0] = inf;root = 0;allnode = n;
        getroot(1,0);
        work(root);
        printf("%.6f
    ",(double)1.0*ans/((double)n*(n-1)/2));
        return 0;
    }

        

  • 相关阅读:
    介绍几个程序员常去的网站
    你这辈子,为什么富不起来?!
    Bug解决:mysql 创建表字段Double类型长度
    RedisTemplate5种数据结构操作
    StringRedisTemplate与RedisTemplate区别
    Redis客户端信息的存取
    Anaconda安装pygame
    springboot启动报错
    idea上传项目到github
    Docker安装报错
  • 原文地址:https://www.cnblogs.com/zxhl/p/7257310.html
Copyright © 2011-2022 走看看