zoukankan      html  css  js  c++  java
  • [HDU5909]Tree Cutting

    题目

      点这里看题目。

    分析

      不难想到这样的 DP :
      (f(u,j)):以(u)为根的连通块中异或值(j)的子树的个数。
      转移类似于背包,设已经合并到(u)上的信息为(g),得到:

    [f(u,j)=sum_{(u,v)in E}sum_{ioplus k=j}g(i)f(v,k) ]

      后面这个异或卷积就可以用 FWT 优化了。总时间复杂度(O(Tnmlog_2m))

    代码

    #include <cstdio>
    
    const int mod = 1e9 + 7, inv2 = 5e8 + 4;
    const int MAXN = 1005, MAXM = ( 1 << 10 ) + 5;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0;char s = getchar();int f = 1;
    	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
    	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
    	if( 9 < x ){ write( x / 10 ); }
    	putchar( x % 10 + '0' );
    }
    
    struct edge
    {
    	int to, nxt;
    }Graph[MAXN << 1];
    
    int val[MAXN][MAXM];
    int head[MAXN], tot[MAXM];
    int N, M, cnt, len;
    
    int fix( const int a ) { return ( a % mod + mod ) % mod; }
    
    void addEdge( const int from, const int to )
    {
    	Graph[++ cnt].to = to, Graph[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    void FWT( int *f, const int mode )
    {
    	int t1, t2;
    	for( int s = 2 ; s <= len ; s <<= 1 )
    		for( int i = 0, t = s >> 1 ; i < len ; i += s )
    			for( int j = i ; j < i + t ; j ++ )
    			{
    				t1 = f[j], t2 = f[j + t];
    				if( mode > 0 ) f[j] = ( t1 + t2 ) % mod, f[j + t] = fix( t1 - t2 );
    				else f[j] = 1ll * ( t1 + t2 ) * inv2 % mod, f[j + t] = 1ll * fix( t1 - t2 ) * inv2 % mod;
    			}
    }
    
    void init()
    {
    	cnt = 0;
    	for( int i = 1 ; i <= N ; i ++ ) head[i] = 0;
    	for( len = 1 ; len < M ; len <<= 1 ) ;
    	for( int i = 1 ; i <= N ; i ++ )
    		for( int j = 0 ; j < len ; j ++ )
    			val[i][j] = 0;
    	for( int i = 0 ; i < M ; i ++ ) tot[i] = 0;
    }
    
    void mul( int *ret, int *multi )
    {
    	for( int i = 0 ; i < len ; i ++ ) 
    		ret[i] = 1ll * ret[i] * multi[i] % mod;
    }
    
    void DFS( const int u, const int fa )
    {
    	FWT( val[u], 1 );
    	for( int i = head[u], v ; i ; i = Graph[i].nxt )
    		if( ( v = Graph[i].to ) ^ fa )
    			DFS( v, u ), mul( val[u], val[v] );
    	FWT( val[u], -1 );
    	( val[u][0] += 1 ) %= mod;
    	FWT( val[u], 1 );
    }
    
    int main()
    {
    	int T;
    	read( T );
    	while( T -- )
    	{
    		read( N ), read( M ); init();
    		for( int i = 1, v ; i <= N ; i ++ ) read( v ), val[i][v] ++;
    		for( int i = 1, a, b ; i < N ; i ++ ) read( a ), read( b ), addEdge( a, b ), addEdge( b, a );
    		DFS( 1, 0 );
    		for( int i = 1 ; i <= N ; i ++ ) FWT( val[i], -1 ), val[i][0] = fix( val[i][0] - 1 );
    		for( int i = 1 ; i <= N ; i ++ )
    			for( int j = 0 ; j < M ; j ++ ) 
    				( tot[j] += val[i][j] ) %= mod;
    		for( int i = 0 ; i < M ; i ++ ) write( tot[i] ), putchar( i == M - 1 ? '
    ' : ' ' );
    	}
    	return 0;
    }
    
  • 相关阅读:
    file & iconv
    UML类图思考
    Rust PhantomData and dropck rgb
    golang recover rgb
    帮上小学的女儿写的一篇文章春夏秋冬
    SAP B1在添加物料主数据时,出现错误提示‘xxxx代码已存在’的解决方法
    SAP B1外协物料处理方法
    SAP B1外发加工件成本的处理方法(曹玉平于奥莱照明)
    SAP B1存在的BUG
    交叉表的实殃及向SQL SERVER数据库中插入数据时,出现乱码或???(问号)的解决方法。
  • 原文地址:https://www.cnblogs.com/crashed/p/12583950.html
Copyright © 2011-2022 走看看