P6624-[省选联考2020A卷]作业题【矩阵树定理,欧拉反演】
正题
题目链接:https://www.luogu.com.cn/problem/P6624
题目大意
\(n\)个点的一张图,每条边有权值,一棵生成树的权值是所有边权和乘上边权的\(gcd\),即
\]
求所有生成树的权值和
解题思路
首先要知道一个东西\(\varphi*I=id\),于是我们就有
\]
然后化进这个式子里就是
\]
然后把\(\varphi(d)\)丢出去就是
\]
之后就是怎么快速算后面那个东西的事情了。
一个比较朴素的做法是枚举每一条边产生的贡献,然后固定这条边然后矩阵树求一次答案乘上这条边就好了。
但是这个比较慢,我们可以利用生成函数的思想,每一条边权变为\(F_i(x)=w_ix+1\)的一个多项式,然后所有多项式乘起来之后的一次项系数就是答案了。因为这样只会选择一条边的\(w_i\)
多项式除法的话用的比较少,这里化一下
\]
然后二次项我们直接丢掉就有
\]
带进后面那个去就有
\]
所以
\]
这样时间复杂度是\(O(\ max\{w_i\}(m+n^3)\ )\)的,好像过不了,可以把边数不够\(n-1\)的直接不管,这样可以省去很多无用情况
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,P=998244353;
struct fuc{
ll x,y;
fuc(ll xx=0,ll yy=0)
{x=xx;y=yy;return;}
};
ll power(ll x,ll b){
ll ans=1;x%=P;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
};
ll inv(ll x){return power(x,P-2);}
fuc operator+(fuc a,fuc b)
{return fuc((a.x+b.x)%P,(a.y+b.y)%P);}
fuc operator-(fuc a,fuc b)
{return fuc((a.x-b.x+P)%P,(a.y-b.y+P)%P);}
fuc operator*(fuc a,fuc b)
{return fuc((a.x*b.y+a.y*b.x)%P,a.y*b.y%P);}
fuc operator/(fuc a,fuc b)
{return fuc((a.x*b.y-b.x*a.y+P)%P*inv(b.y*b.y)%P,a.y*inv(b.y)%P);}
ll n,m,ans,x[N],y[N],w[N],phi[N],pri[N],cnt;
bool v[N];fuc a[31][31];
fuc det(){
fuc ans(0,1);ll f=1;
for(ll i=1;i<n;i++){
ll w=i;
for(ll j=i;j<n;j++)
if(a[i][j].y){
if(i!=j)f=-f;
w=j;break;
}
swap(a[i],a[w]);
if(!a[i][i].y)return fuc(0,0);
ans=ans*a[i][i];
fuc inv=fuc(0,1)/a[i][i];
for(ll j=n-1;j>=i;j--)
a[i][j]=a[i][j]*inv;
for(ll j=i+1;j<n;j++){
fuc rate=a[j][i];
for(ll k=i;k<n;k++)
a[j][k]=a[j][k]-rate*a[i][k];
}
}
return (ans.x*f+P)%P;
}
void init(ll n){
phi[1]=1;
for(ll i=2;i<=n;i++){
if(!v[i])pri[++cnt]=i,phi[i]=i-1;
for(ll j=1;j<=cnt&&i*pri[j]<=n;j++){
v[i*pri[j]]=1;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*phi[pri[j]];
}
}
return;
}
signed main()
{
scanf("%lld%lld",&n,&m);
ll mx=0;
for(ll i=1;i<=m;i++){
scanf("%lld%lld%lld",&x[i],&y[i],&w[i]);
x[i]--;y[i]--;mx=max(mx,w[i]);
}
init(mx);
for(ll i=1;i<=mx;i++){
ll cnt=0;
for(ll j=1;j<=m;j++)
if(w[j]%i==0)cnt++;
if(cnt<n-1)continue;
memset(a,0,sizeof(a));
for(ll j=1;j<=m;j++)
if(w[j]%i==0){
a[x[j]][x[j]]=a[x[j]][x[j]]+fuc(w[j],1);
a[y[j]][y[j]]=a[y[j]][y[j]]+fuc(w[j],1);
a[x[j]][y[j]]=a[x[j]][y[j]]-fuc(w[j],1);
a[y[j]][x[j]]=a[y[j]][x[j]]-fuc(w[j],1);
}
(ans+=phi[i]*det().x%P)%=P;
}
printf("%lld\n",ans);
return 0;
}
P6624-[省选联考2020A卷]作业题【矩阵树定理,欧拉反演】的更多相关文章
- P6620-[省选联考2020A卷]组合数问题【组合数学,斯特林数】
正题 题目链接:https://www.luogu.com.cn/problem/P6620 题目大意 给出\(n,x,p,m\)和一个\(m\)次多项式\(f\)求 \[\sum_{k=0}^nf( ...
- 洛谷 P6624 - [省选联考 2020 A 卷] 作业题(矩阵树定理+简单数论)
题面传送门 u1s1 这种题目还是相当套路的罢 首先看到 \(\gcd\) 可以套路地往数论方向想,我们记 \(f_i\) 为满足边权的 \(\gcd\) 为 \(i\) 的倍数的所有生成树的权值之和 ...
- P7515-[省选联考 2021A卷]矩阵游戏【差分约束】
正题 题目链接:https://www.luogu.com.cn/problem/P7515 题目大意 有一个\(n*m\)的矩形\(A\),然后给出一个\((n-1)*(m-1)\)的矩形\(B\) ...
- luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理)
luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理) Luogu 题外话: Day2一题没切. 我是傻逼. 题解时间 某种意义上说刻在DNA里的柿子,大概是很多人学 ...
- 题解 P6622 [省选联考 2020 A/B 卷] 信号传递
洛谷 P6622 [省选联考 2020 A/B 卷] 信号传递 题解 某次模拟赛的T2,考场上懒得想正解 (其实是不会QAQ), 打了个暴力就骗了\(30pts\) 就火速溜了,参考了一下某位强者的题 ...
- [省选联考 2020 A 卷] 组合数问题
题意 [省选联考 2020 A 卷] 组合数问题 想法 自己在多项式和数论方面还是太差了,最近写这些题都没多少思路,看完题解才会 首先有这两个柿子 \(k*\dbinom{n}{k} = n*\dbi ...
- [省选联考 2021 A 卷] 矩阵游戏
很巧妙的一个构造. 我是没有想到的. 自己的思维能力可能还是不足. 考虑先满足\(b\)对\(a\)的限制,把\(a\)的第一行和第一列设\(0\),推出这个\(a\). 接下来考虑对这个\(a\), ...
- [省选联考 2021 A/B 卷] 卡牌游戏
垃圾福建垫底选手来看看这题. 大家怎么都写带 \(log\) 的. 我来说一个线性做法好了. 那么我们考虑枚举 \(k\) 作为翻转完的最小值. 那么构造出一个满足条件的操作,我们在 \(a_i\) ...
- luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp)
luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp) Luogu 题外话: 我可能是傻逼, 但不管我是不是傻逼, 我永远单挑出题人. 题解时间 看数据范围可以确定状压dp. ...
随机推荐
- Spring-Boot的动态代理AOP原理
前言 Spring AOP使用了动态代理技术,动态代理在业界比较流行的实现方式有,CGLIB,Javassist,ASM等等. Spring动态代理实现方式 Spring采用了JDK和CGLIB两种方 ...
- java 日期格式化-- SimpleDateFormat 的使用。字符串转日期,日期转字符串
日期和时间格式由 日期和时间模式字符串 指定.在 日期和时间模式字符串 中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' 被解释为模式字母,用来表示日期或时间字符串元素.文本可以使用单引 ...
- jQuery中获取属性值:attr()、html()、text()、val()等(一)
<!DOCTYPE html> <html> <head> <title>01_basic.html</title> <meta na ...
- MySql 改变table的列名以及列的类型
1 ALTER TABLE table_name CHANGE COLUMN old_col_name new_col_name datatype; #改变table的列名以及列的类型
- Servlet体系及方法
时间:2016-11-11 15:07 --Servlet体系Servlet(interface): 实现类:GenericServlet.HttpServletServletConfig(in ...
- HTML5存储 ——Web Storage(localStorage 和 sessionStorage)
一.localStorage对象临时储存API 方法: 1.localStorage.setItem(key,value)---设置存储内容 2.localStorage.getItem(key)-- ...
- 在Raspberry Pi 3B+上安装Windows 10 IoT
下载 进入树莓派下载页面,当前网址https://www.raspberrypi.org/downloads/ 选择Windows 10 IoT Core,当前网址https://docs.micro ...
- EternalBlue永恒之蓝渗透测试
Eternal Blue(永恒之蓝)-ms17-010渗透测试 第一次做的渗透测试,也是第一次去写博客,还望各位师傅多多指正 :) 工具 1.靶机系统 window7 开放445以及139端口 2.k ...
- 20200713晚 noip14
考场 很紧张,上午考太烂了 开场看到"影魔",想起以前看过(但没做),心态爆炸,咆哮时被 hkh diss 了 T1 一开始想建边跑最长路,每个点在记录一下 \(\min\{a\} ...
- 第二课:启动 GDB 调试
使用 GDB 调试程序一般有三种方式: gdb filename gdb attach pid gdb filename corename 这也对应着本节课的核心内容: 直接调试目标程序 附加进程 调 ...