zoukankan      html  css  js  c++  java
  • Solution -「多校联训」种蘑菇

    (mathcal{Description})

      Link.

      给定一棵含有 (n) 个结点的树,设 (S) 为其中的非空联通子集,求

    [sum_{S}(gcd_{uin S}u)^{|S|}. ]

      (nle2 imes10^5)

    (mathcal{Solution})

      直接莫反(为什么当时我迟疑那么久 qwq):

    [sum_{S}(gcd_{uin S}u)^{|S|}=sum_{d=1}^nsum_{dt|s_j,j=1,2,cdots,|S|}mu(t)sum_{S}d^{|S|}. ]

    前两层直接枚举,最后一个简单树上 DP,复杂度是

    [sum_{i=1}^nsum_{j=1}^{frac{n}i}mathcal O(frac{n}{ij})=mathcal O(nln^2 n)? ]

      记得提醒我看见 (gcd) 不要忘了莫反这家伙。(

    (mathcal{Code})

    /* Clearink */
    
    #include <cstdio>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    inline int rint() {
    	int x = 0, f = 1, s = getchar();
    	for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
    	for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
    	return x * f;
    }
    
    template<typename Tp>
    inline void wint( Tp x ) {
    	if ( x < 0 ) putchar( '-' ), x = -x;
    	if ( 9 < x ) wint( x / 10 );
    	putchar( x % 10 ^ '0' );
    }
    
    const int MAXN = 2e5, MOD = 1e9 + 7;
    int n, ecnt, head[MAXN + 5];
    struct Edge { int to, nxt; } graph[MAXN * 2 + 5];
    
    inline int mul( const long long a, const int b ) { return a * b % MOD; }
    inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
    inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
    inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
    inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
    
    inline void link( const int u, const int v ) {
    	graph[++ecnt] = { v, head[u] }, head[u] = ecnt;
    	graph[++ecnt] = { u, head[v] }, head[v] = ecnt;
    }
    
    int pn, mu[MAXN + 5], pr[MAXN + 5];
    bool npr[MAXN + 5];
    
    inline void sieve( const int n ) {
    	mu[1] = 1;
    	rep ( i, 2, n ) {
    		if ( !npr[i] ) mu[pr[++pn] = i] = -1;
    		for ( int j = 1, t; j <= pn && ( t = i * pr[j] ) <= n; ++j ) {
    			npr[t] = true;
    			if ( !( i % pr[j] ) ) break;
    			mu[t] = -mu[i];
    		}
    	}
    }
    
    bool vis[MAXN + 5];
    int f[MAXN + 5];
    
    inline void dfs( const int u, const int bas, const int fac ) {
    	vis[u] = true, f[u] = bas;
    	for ( int i = head[u], v; i; i = graph[i].nxt ) {
    		if ( !vis[v = graph[i].to] && !( v % fac ) ) {
    			dfs( v, bas, fac ), addeq( f[u], mul( f[u], f[v] ) );
    		}
    	}
    }
    
    inline int solve( const int bas, const int fac ) {
    	for ( int i = fac; i <= n; i += fac ) if ( !vis[i] ) dfs( i, bas, fac );
    	int ret = 0;
    	for ( int i = fac; i <= n; i += fac ) addeq( ret, f[i] ), vis[i] = false;
    	return ret;
    }
    
    int main() {
    	freopen( "mushroom.in", "r", stdin );
    	freopen( "mushroom.out", "w", stdout );
    
    	n = rint();
    	rep ( i, 2, n ) link( rint(), rint() );
    
    	sieve( n );
    
    	int ans = 0;
    	rep ( i, 1, n ) rep ( j, 1, n / i ) {
    		addeq( ans, ( solve( i, i * j ) * mu[j] + MOD ) % MOD );
    	}
    
    	wint( ans ), putchar( '
    ' );
    	return 0;
    }
    
    
    
  • 相关阅读:
    (转) Android的Window类
    android 打开文件
    Android线程优先级
    Hierarchy viewer problems
    android:windowSoftInputMode
    (转) Android 安全机制
    Mobl试用之helloword
    写给自己对软件测试经历的总结
    Mobl试用二
    黑马程序员面向对象基础:属性和方法
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14901376.html
Copyright © 2011-2022 走看看