考虑到删点操作的实质是指认边的方向。

由于这是一棵树,所以有很好的性质。

我们完全可以以此从树叶开始,往上拓扑进行,按照对某个数的取膜的大小来进行操作。

由此可知,除了 \(1\) 以外,任意 \(2 \leq k\) 都有可能,且只有一种方案。

那么如何判断方案是当下的问题。

考虑到我们的的操作过程,我们发现其实在每个质数的同余系下,有且只有一个答案可能存在。

又由于 \(m = n - 1 = \sum a[i]\),那么我们把 \(m\) 质数分解,对这些质数的同余系进行讨论就好。

同时总方案数为 \(2 ^ {n - 1}\) ,依照容斥原理,那么 \(k = 1\) 时答案为 \(2 ^ {n - 1} - \sum_{i = 2} f[i]\)

#include<iostream>
#include<cstdio>
#include<queue>
#define ll long long
#define N 100005
#define mod 998244353 ll T;
ll n;
ll head[N],cnt;
ll in[N],iin[N];
ll a[N],b[N];
ll f[N]; struct P{
int to,next;
}e[N << 1]; inline void clear(){
for(int i = 1;i <= n;++i)
head[i] = in[i] = iin[i] = a[i] = b[i] = 0,f[i] = 0;
for(int i = 1;i <= cnt;++i)
e[i].to = e[i].next = 0;
cnt = 0; } inline void add(int x,int y){
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
in[y] ++ ;
} inline ll qpow(ll a,ll b){
ll ans = 1;
while(b){
if(b & 1)ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
} std::queue<int>QWQ; ll vis[N]; inline ll gcd(ll x,ll y){
return (x == 0) ? y : gcd(y % x,x);
} inline ll find(ll x){//找出在该同余系下的答案。
for(int i = 1;i <= n;++i)
iin[i] = in[i],a[i] = b[i] = 0,vis[i] = 0;
for(int i = 1;i <= n;++i)
if(iin[i] == 1)//成为叶子
QWQ.push(i);
while(QWQ.size()){
int u = QWQ.front();
QWQ.pop();
vis[u] = 1;
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(vis[v])continue;
if(a[u] == 0)a[v] = (a[v] + 1) % x,b[v] ++ ;else a[u] = (a[u] + 1) % x,b[u] ++;
iin[v] -- ;
if(iin[v] == 1)
QWQ.push(v);
}
}
ll ans = b[1];
for(int i = 2;i <= n;++i)
ans = gcd(ans,b[i]);
return ans;
} int main(){
scanf("%lld",&T);
while(T -- ){
scanf("%lld",&n);
clear();
for(int i = 1;i <= n - 1;++i){
ll x,y;
scanf("%lld%lld",&x,&y);
add(x,y);
add(y,x);
}
ll m = n - 1;
for(int i = 2;i * i <= m;++i){
if(m % i == 0){
ll si = find(i);
if(si % i == 0)
f[si] = 1 ;
while(m % i == 0 && i != 1)m /= i;
}
}
if(m > 1){
ll si = find(m);
if(si % m == 0)
f[si] = 1 ;
}
f[1] = (f[1] + qpow(2,n - 1)) % mod;
for(int i = 2;i <= n;++i)
f[1] = (f[1] - f[i] + mod) % mod;
for(int i = 1;i <= n;++i)
std::cout<<f[i]<<" ";
puts("");
}
}

CF1554E You的更多相关文章

  1. Involuting Bunny! (2021.8)

      CF1555F & Submission.   Tags:「A.生成树」「B.Tricks」   分类处理询问的 trick:连接两个连通块的边显然合法,先用这些边构建生成森林.发现每条边 ...

随机推荐

  1. CentOS 用户与群组

    目录 1.用户管理 1.1.切换用户 1.2.添加用户 1.3.删除用户 1.4.修改用户 2.群组管理 2.1.查看群组 2.2.添加群组 2.3.删除群组 2.4.修改群组 1.用户管理 Linu ...

  2. C语言链表实例--玩转链表

    下图为最一简单链表的示意图: 第 0 个结点称为头结点,它存放有第一个结点的首地址,它没有数据,只是一个指针变量.以下的每个结点都分为两个域,一个是数据域,存放各种实际的数据,如学号 num,姓名 n ...

  3. PriorityQueue(优先队列)

    PriorityQueue 翻译过来就是优先队列,本质是一个堆, 默认情况下堆顶每次都保留最小值,每插入一个元素,仍动态维护堆顶为最小值. PriorityQueue 一个基于优先级的无界优先级队列. ...

  4. 21.10.9 test

    T1 购票方案 \(\color{green}{100}\) 对于每个时间节点维护它作为每种票所能包含的最后一个点时,这种票的起始点位置,由于这个位置是单调的,所以类似双指针维护,\(O(KN)\) ...

  5. HCNP Routing&Switching之BGP路由属性和优选规则

    前文我们了解了BGP防环机制和路由聚合相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15458110.html:今天我们来聊一聊BGP路由属性和选路规 ...

  6. vim实用插件

    转载:Vim 实用插件推荐(2017) - 知乎 (zhihu.com) 1.插件管理器 ----------------------------------------- Vundle.vim - ...

  7. 问题解决:补充安装c语言的库函数和系统调用man手册

    问题解决:补充安装c语言的库函数和系统调用man手册 ​ 今日份麻麻~上课时大家的Ubuntu都可以通过man查到关于stat的库函数,但是我的Kali查出来是这样: ​ 询问老师之后得知需要去安装相 ...

  8. Docker 18.03导入导出

    docker中分容器和镜像,简单可以理解为容器是运行中的实例,镜像是运行实例所需的静态文件. 导入导出既可以对容器做操作,也可以对镜像做操作.区别在于镜像可以随时导出,容器必须要停止之后才可以导出,否 ...

  9. native连接远程mysql数据库

    1.环境 CentOS7.mysqld 8.0.19 2.登录数据库 #mysql -u root -p 2.修改root登录地址为%(任何IP) mysql> update user set ...

  10. Git+windows安装教程(一)

    一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...