Live2D

Solution -「多校联训」种蘑菇

Description

  Link.

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

S(gcduSu)|S|.

  n2×105

Solution

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

S(gcduSu)|S|=d=1ndt|sj,j=1,2,,|S|μ(t)Sd|S|.

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

i=1nj=1niO(nij)=O(nln2n)?

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

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( '\n' );
	return 0;
}


posted @   Rainybunny  阅读(53)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示