luogu 3790 文艺数学题 - 矩阵树定理 - 容斥原理
可以考虑计算边权的最大公约数为$i$的生成树的个数$f(i)$,最后累加答案。
然后考虑这样的生成树的个数怎么求,根据某个经典套路,我们可以容斥。
因为可以求出边权的最大公约数为$i$的倍数的生成树的个数$F(i)$,所以减去它的倍数的$f$就是$f(i)$了。
但是这么做会T掉。
可以用$O(W\log W)$的时间内预处理出为边权$i$的倍数的边数有多少条。然后高消前判断一下边数是否大于等于$n - 1$。
具体有关时间复杂度的证明可以在洛谷的题解中找到,这里就不给出了。
Code
/**
* luogu
* Problem#3790
* Accepted
* Time: 6016ms
* Memory: 9402k
*/
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef bool boolean;
#define ll long long const int N = , M = 1e9 + ; void exgcd(int a, int b, int& d, int& x, int& y) {
if(!b)
d = a, x = , y = ;
else {
exgcd(b, a % b, d, y, x);
y -= (a / b) * x;
}
} int inv(int a, int n) {
int d, x, y;
exgcd(a, n, d, x, y);
return (x < ) ? (x + n) : (x);
} typedef class Matrix {
public:
int a[N][N]; void reset() {
memset(a, , sizeof(a));
} int det(int n) {
int pro = ;
for (int i = , e; i <= n; i++) {
e = ;
for (int j = i; j <= n && !e; j++)
if (a[j][i])
e = j;
if (e == ) return ;
if (e != i)
for (int j = ; j <= n; j++)
swap(a[e][j], a[i][j]);
for (int j = , x, y; j <= n; j++) {
if (j == i) continue;
x = a[i][i], y = a[j][i], pro = pro * 1ll * x % M;
for (int k = ; k <= n; k++) {
a[j][k] = (a[j][k] * 1ll * x - a[i][k] * 1ll * y) % M;
if (a[j][k] < ) a[j][k] += M;
} }
}
int rt = inv(pro, M);
for (int i = ; i <= n; i++)
rt = rt * 1ll * a[i][i] % M;
return rt;
}
}Matrix; typedef class Edge {
public:
int u, v, w;
}Edge; const int Val = 1e6 + ; int n, m;
Edge* es;
Matrix a;
int ce[Val], f[Val]; inline void init() {
scanf("%d%d", &n, &m);
es = new Edge[(m + )];
for (int i = ; i <= m; i++)
scanf("%d%d%d", &es[i].u, &es[i].v, &es[i].w), ce[es[i].w]++;
} int calc(int g) {
if (ce[g] < n - ) return ;
a.reset();
for (int i = , u, v; i <= m; i++)
if (!(es[i].w % g)) {
u = es[i].u - , v = es[i].v - ;
a.a[u][u]++, a.a[v][v]++;
a.a[u][v]--, a.a[v][u]--;
if (a.a[u][v] < ) a.a[u][v] += M;
if (a.a[v][u] < ) a.a[v][u] += M;
}
int rt = a.det(n - );
// cerr << rt << endl;
return rt;
} int res = ;
inline void solve() {
for (int i = ; i < Val; i++)
for (int j = (i << ); j < Val; j += i)
ce[i] += ce[j];
for (int i = Val - ; i; i--) {
f[i] = calc(i);
for (int j = (i << ); j < Val; j += i) {
f[i] -= f[j];
if (f[i] < )
f[i] += M;
}
res = (res + f[i] * 1ll * i) % M;
}
printf("%d", res);
} int main() {
init();
solve();
return ;
}
luogu 3790 文艺数学题 - 矩阵树定理 - 容斥原理的更多相关文章
- Luogu P4336 [SHOI2016]黑暗前的幻想乡 矩阵树定理+容斥原理
真是菜到爆炸....容斥写反(反正第一次写qwq) 题意:$n-1$个公司,每个公司可以连一些边,求每个边让不同公司连的生成树方案数. 矩阵树定理+容斥原理(注意到$n$不是很大) 枚举公司参与与否的 ...
- 【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理
题目描述 给出 $n$ 个点和 $n-1$ 种颜色,每种颜色有若干条边.求这张图多少棵每种颜色的边都出现过的生成树,答案对 $10^9+7$ 取模. 输入 第一行包含一个正整数 N(N<=17) ...
- bzoj 4596: [Shoi2016]黑暗前的幻想乡【容斥原理+矩阵树定理】
真是简单粗暴 把矩阵树定理的运算当成黑箱好了反正我不会 这样我们就可以在O(n^3)的时间内算出一个无向图的生成树个数了 然后题目要求每个工程队选一条路,这里可以考虑容斥原理:全选的方案数-不选工程队 ...
- BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]
传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...
- 【BZOJ 4596】 4596: [Shoi2016]黑暗前的幻想乡 (容斥原理+矩阵树定理)
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 324 Solved: 187 Description ...
- 【Luogu】P3317重建(高斯消元+矩阵树定理)
题目链接 因为这个专门跑去学了矩阵树定理和高斯消元qwq 不过不是很懂.所以这里只放题解 玫葵之蝶的题解 某未知dalao的矩阵树定理 代码 #include<cstdio> #inclu ...
- 【BZOJ4596】【Luogu P4336】 [SHOI2016]黑暗前的幻想乡 矩阵树定理,容斥
同样是矩阵树定理的裸题.但是要解决它需要能够想到容斥才可以. \(20\)以内的数据范围一定要试试容斥的想法. #include <bits/stdc++.h> using namespa ...
- 【BZOJ4596】[Shoi2016]黑暗前的幻想乡 容斥+矩阵树定理
[BZOJ4596][Shoi2016]黑暗前的幻想乡 Description 幽香上台以后,第一项措施就是要修建幻想乡的公路.幻想乡有 N 个城市,之间原来没有任何路.幽香向选民承诺要减税,所以她打 ...
- 洛谷 P4336 黑暗前的幻想乡 —— 容斥+矩阵树定理
题目:https://www.luogu.org/problemnew/show/P4336 当作考试题了,然而没想出来,呵呵. 其实不是二分图完美匹配方案数,而是矩阵树定理+容斥... 就是先放上所 ...
随机推荐
- Mac为python2.7.10安装pip
首先下载get-pip.py https://bootstrap.pypa.io/get-pip.py alias python="/usr/bin/python2.7" pyth ...
- Pycharm进行版本管理
即然pycharm为python提供了这么强大的IDE,那么,我们代码管理,没理由不用版本管理工具Git,SVN等等 在pychram中使用GitHub进行代码管理;需要准备: 1)GitHub帐号: ...
- 根据异常自定义处理逻辑(【附】java异常处理规范)
▄︻┻┳═一『异常捕获系列』Agenda: ▄︻┻┳═一有关于异常捕获点滴,plus我也揭揭java的短 ▄︻┻┳═一根据异常自定义处理逻辑([附]java异常处理规范) ▄︻┻┳═一利用自定义异常来 ...
- Cassandra创建第一个用户
Cassandra配置文件cassandra.yaml 的配置项, 默认是 authenticator: AllowAllAuthenticator 现在想创建Cassandra的用户,但是如果保持以 ...
- 《大话设计模式》c++实现 原型模式
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 主要解决:在运行期建立和删除原型. 何时使用: 1.当一个系统应该独立于它的产品创建,构成和表示时. 2.当要实例化的类是在运行 ...
- Problem(莫比乌斯反演)
我不是传送门 题意 : 中文题目不解释 求gcd(x,y) = k (a<=x<=b, c<=y<=d); 根据gcd(ka,kb) = k*gcd(a,b), 可将问题转化为 ...
- Java输入输出流(IO)-----文件类File详解
1.java.io.File类简介 凡是与输入.输出相关的类.接口等都定义在java.io包下 File是一个类,可以有构造器创建其对象.此对象对应着一个文件(.txt .avi .doc .p ...
- rest-framework 序列化格式Restful API设计规范
理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...
- 32个使用python代码片段
1.冒泡排序 lis = [56,12,1,8,354,10,100,34,56,7,23,456,234,-58] def sortport(): for i in range(len(lis ...
- Linux基础命令---ping
ping ping指令可以发送ICMP请求到目标地址,如果网络功能正常,目标主机会给出回应信息.ping使用ICMP协议强制发送ECHO_REQUEST报文到目标主机,从主机或网关获取ICMP ECH ...