zoukankan      html  css  js  c++  java
  • HDU 4670 Cube number on a tree ( 树的点分治 )

    题意 : 给你一棵树 。 树的每一个结点都有一个权值 。 问你有多少条路径权值的乘积是一个全然立方数 。

    题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数


    思路 : 一个全然立方数的素因子个数都是三的倍数 , 所以我们仅仅要求各个素数的个数即可了 , 而且我们仅仅关心个数对三的余数

    所以我们能够用一个 长整形来表示每一个结点到根的各个素因子的个数( 三进制压缩 ) 。

    只是由于用位运算会快一点 , 所以我用了四进制。即每两位表示一个素因子的个数 。

    中间合并的时候计算刚好相加之后变成0的数,然后用map统计就能够了


    注意 : 题目中 pi 的值 , 0 是取不到的(  纠结了好久该怎么处理 = = )


    #include <stdio.h>
    #include <string.h>
    #include <map>
    #include <algorithm>
    #pragma comment(linker, "/STACK:102400000,102400000")
    using namespace std;
    
    #define MAXN 50005
    #define INF 0x3f3f3f3f
    __int64 prime[35] ;
    int n , k ;
    
    struct Tree{  
        struct Edge{  
            int to , nex ;  
            Edge(){}  
            Edge( int _to  , int _nex ) {  
                to = _to ;  
                nex = _nex ;  
            }  
        }edge[MAXN*2] ;  
    
        int head[MAXN] ;  
        int Index ;  
      
        void init(){  
            memset( head , -1 , sizeof(head) ) ;  
            Index = 0 ;  
        }  
      
        void add( int from , int to ) {  
            edge[Index] = Edge( to , head[from] ) ;  
            head[from] = Index ++ ;  
        }  
    } tree ;
    
    inline int get( __int64 val , int pos ) {
        return ( val >> ( pos << 1 ) ) & 3 ;
    }
    
    inline void set( __int64 & val , int pos , int k ) {
        val |= ( (__int64)k << ( pos << 1 ) ) ;
    }
    
    __int64 add( __int64 a , __int64 b ) {
        __int64 ans = 0 ;
        for( int i = 0 ; i < k ; i ++ ) {
            int aa = get( a , i ) ;
            int bb = get( b , i ) ;
            aa += bb ;
            aa %= 3 ; ;
            set( ans , i , aa ) ;
        }
        return ans ;
    }
    
    __int64 fan( __int64 a  ) {
        __int64 ans = 0 ;
        for( int i = 0 ; i < k ; i ++ ) {
            int tmp = get( a , i ) ;
            tmp =  3 - tmp ;
            set( ans , i , tmp % 3 ) ;
        }
        return ans ;
    }
    
    bool vis[MAXN] ;
    __int64 val[MAXN] ;
    __int64 ans ;
    
    // 第i结点为根的子树的最大个数  
    int dp[MAXN] ;  
    // 第i结点为根的子树的大小  
    int sum[MAXN] ;  
    
    int Sum ;  
    int Min , Minid ;  
    
    void dfs1( int u , int f ) {  
        sum[u] = 1 ;  
        dp[u] = 0 ;  
        for( int i = tree.head[u] ; ~i ; i = tree.edge[i].nex ) {  
            int ch = tree.edge[i].to ;  
            if( ch == f || vis[ch] ) continue ;  
            dfs1( ch , u  ) ;  
            sum[u] += sum[ch] ;  
            dp[u] = max( dp[u] , sum[ch] ) ;  
        }  
    }  
      
    void dfs2( int u , int f ) {  
        int M = max( dp[u] , Sum - sum[u] ) ;  
        if( M < Min ) {  
            Min = M ;  
            Minid = u ;  
        }  
        for( int i = tree.head[u] ; ~i ; i = tree.edge[i].nex ) {  
            int ch = tree.edge[i].to ;  
            if( ch == f || vis[ch] ) continue ;  
              
            dfs2( ch , u ) ;  
        }  
    }  
      
    // 返回树的重心  
    int getRoot( int u ) {  
        // 第一遍dfs求出全部点的子树大小。和以孩子为跟的子树个数的最大值  
        dfs1( u , 0 ) ;  
        Sum = sum[u] ;  
        Min = 0x3f3f3f3f ;  
        Minid = -1 ;  
        // 第二次dfs求重心  
        /* 事实上假设整棵树求重心的话,我们一边dfs即可。由于这个是部分树,我们要dfs来确定哪些结点在当前树中 */  
        dfs2( u , 0 ) ;  
        return Minid ;  
    }  
    
    int tot ;
    __int64 Val[MAXN] ;
    
    void getVal( int u , int fa , __int64 vv ) {
        Val[tot++] = add( vv , val[u] ) ;
        for( int i = tree.head[u] ; ~i ; i = tree.edge[i].nex ) {
            int to = tree.edge[i].to ;
            if( vis[to] == true ) 
                continue ;
            if( to == fa ) continue ;
            getVal( to , u , add( vv , val[u] ) ) ;
        }
    }
    
    map<__int64,int> mp ;
    
    __int64 cal( int root , __int64 val , __int64 root_val ) {
        tot = 0 ;
        getVal( root , 0 , val ) ;
        //sort( Val , Val + tot ) ;
        mp.clear() ;
        __int64 ans = 0 ;
        for( int i = 0 ; i < tot ; i ++ ) {
            ans += mp[ add( root_val , fan(Val[i]) ) ] ;
            mp[Val[i]] ++ ;
        }
        return ans ;
    }
    
    void solve( int u ) {  
        // 得到当前子树的重心  
        int root = getRoot( u ) ;  
        // 计算以root为根的结果  
        ans += cal( root , 0 , val[root] ) ;  
        if( val[root] == 0 ) ans ++ ;
        vis[root] = true ;  
        for( int i = tree.head[root] ; ~i ; i = tree.edge[i].nex ) {  
            int ch = tree.edge[i].to ;  
            if( vis[ch] ) continue ;  
            ans -= cal( ch , val[root] , val[root] ) ;  
            solve( ch ) ;     
        }  
    }
    
    int main(){
        while( scanf( "%d" , &n ) != EOF )  {
            scanf( "%d" , &k ) ;
            for( int i = 0 ; i < k ; i ++ ) {
                scanf( "%d" , &prime[i] ) ;
            }
            tree.init() ;
            memset( vis , false , sizeof(vis) );
            memset( val , 0 , sizeof(val) ) ;
            for( int i = 1 ; i <= n ; i ++ ) {
                __int64 tmp ;
                scanf( "%I64d" , &tmp ) ;
                for( int j = 0 ; j < k ; j ++ ) {
                    int cnt = 0 ;
                    while( tmp % prime[j] == 0 ) {
                        cnt ++ ;
                        tmp /= prime[j] ;
                    }
                    cnt %= 3 ;
                    set( val[i] , j , cnt ) ;
                }
            }
            for( int i = 0 ; i < n - 1 ; i ++ ) {
                int u , v ;
                scanf( "%d%d" , &u , &v ) ;
                tree.add( u , v ) ;
                tree.add( v , u ) ;
            }
            ans = 0 ;
            solve( 1 ) ;
            printf( "%I64d
    " , ans ) ;
        }
        return 0 ;
    }
    


  • 相关阅读:
    Lighthead SiteCrawler
    svnbook
    SFTP in Python: Really Simple SSH
    WP Robot Wordpress plugin logo
    use curl to post data for work punch
    Setting up Hudson on port 80 on a Debian or Ubuntu machine
    Problem with PEXPECT in Python
    H2 Database Engine — h2database.com — Readability
    execnet: rapid multiPython deployment
    Maven问题总结 3 技术改变生活商业成就梦想 51CTO技术博客
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/6705894.html
Copyright © 2011-2022 走看看