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 当作考试题了,然而没想出来,呵呵. 其实不是二分图完美匹配方案数,而是矩阵树定理+容斥... 就是先放上所 ...
随机推荐
- VB脚本错误,系统找不到制定的文件 。代码:80070002
希望得到网友的答案:非常感谢!
- LeetCode111.二叉树的最小深度
给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null,15,7], ...
- 如何注销Sitecore CMS
登录Sitecore很容易,但是在旧版本的Sitecore中使用不同的界面,退出可能会给未经证实的人带来挑战. Sitecore 8 Sitecore 6和7 Sitecore 8 Sitecore ...
- flask模板应用-消息闪现(flash())
消息闪现 flask提供了一个非常有用的flash()函数,它可以用来“闪现”需要提示给用户的消息,比如当用户登录成功后显示“欢迎回来!”.在视图函数调用flash()函数,传入消息内容,flash( ...
- 20165215 2017-2018-2 《Java程序设计》第6周学习总结
20165215 2017-2018-2 <Java程序设计>第6周学习总结 教材学习内容总结 chapter8 Java把String类定义为final类,即String类不能有子类 用 ...
- javascript常用积累
一.JS动画与动作不一致解决: if(!$( "#handle").is(":animated")){ //判断元素是否处于动画状态 } 二.停止事件冒泡 ev ...
- Linux基础命令---文本格式转换fmt
fmt 将指定文件的内容,按照指定的格式重新排版,结果送到标准输出. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 ...
- case when then的用法
用法一:等值判断,相当于switch CASE expression WHEN value1 THEN returnValue1 WHEN value2 THEN returnValue2 WHEN ...
- ESXi 嵌套KVM虚拟化 配置
VMware ESXi5.x默认不支持嵌套虚拟化,需要修改相关配置才能支持 1.ESXi5.1主机开通ssh,修改VMware ESXi配置文件使之嵌套虚拟化. 在配置文件后面加入如下配置:vhv ...
- Python+OpenCV图像处理(二)——打印图片属性、设置图片存储路径、电脑摄像头的调取和显示
一. 打印图片属性.设置图片存储路径 代码如下: #打印图片的属性.保存图片位置 import cv2 as cv import numpy as np #numpy是一个开源的Python科学计算库 ...