LOJ#6271. 「长乐集训 2017 Day10」生成树求和 加强版
由于是边权三进制不进位的相加,那么可以考虑每一位的贡献
对于每一位,生成树的边权相当于是做模 \(3\) 意义下的加法
考虑最后每一种边权的生成树个数,这个可以直接用生成函数,在矩阵树求解的时候做一遍这个生成函数的模 \(3\) 意义下的循环卷积求出系数即可
暴力多项式运算不可取
考虑选取 \(3\) 个数字 \(x_i\),使得 \(x_i^3\equiv1(mod~10^9+7)\)
即找出 \(3\) 次单位复数根 \(\omega_3^0,\omega_3^1,\omega_3^2\)
这个直接带入三角表示法即可得到
把这些东西带入,矩阵树定理求出点值,最后手动 \(DFT^{-1}\) 即可
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod(1e9 + 7);
const int inv2((mod + 1) >> 1);
const int inv3((mod + 1) / 3);
const int rt3(82062379);
inline int Pow(ll x, int y) {
ll ret = 1;
for (; y; y >>= 1, x = x * x % mod)
if (y & 1) ret = ret * x % mod;
return ret;
}
inline void Inc(int &x, int y) {
x = x + y >= mod ? x + y - mod : x + y;
}
inline void Dec(int &x, int y) {
x = x - y < 0 ? x - y + mod : x - y;
}
inline int Add(int x, int y) {
return x + y >= mod ? x + y - mod : x + y;
}
inline int Sub(int x, int y) {
return x - y < 0 ? x - y + mod : x - y;
}
struct Complex {
int a, b;
inline Complex(int _a = 0, int _b = 0) {
a = _a, b = _b;
}
inline Complex operator +(Complex y) const {
return Complex(Add(a, y.a), Add(b, y.b));
}
inline Complex operator -(Complex y) const {
return Complex(Sub(a, y.a), Sub(b, y.b));
}
inline Complex operator *(Complex y) const {
return Complex(Sub((ll)a * y.a % mod, (ll)b * y.b % mod), Add((ll)a * y.b % mod, (ll)b * y.a % mod));
}
inline Complex operator *(int y) const {
return Complex((ll)a * y % mod, (ll)b * y % mod);
}
inline Complex operator /(int y) const {
int inv = Pow(y, mod - 2);
return Complex((ll)a * inv % mod, (ll)b * inv % mod);
}
inline Complex operator /(Complex y) const {
return Complex(a, b) * Complex(y.a, mod - y.b) / Add((ll)y.a * y.a % mod, (ll)y.b * y.b % mod);
}
} a[105][105], coef[3], inv, w[3], invw[3];
int n, m, eu[105 * 105], ev[105 * 105], ec[105 * 105], bin[20];
inline Complex Det() {
int i, j, k;
Complex ret = Complex(1, 0);
for (i = 1; i < n; ++i) {
for (j = i; j < n; ++j)
if (a[j][i].a || a[j][i].b) {
if (i == j) break;
swap(a[i], a[j]), ret = ret * (mod - 1);
break;
}
for (j = i + 1; j < n; ++j) {
inv = a[j][i] / a[i][i];
for (k = i; k < n; ++k) a[j][k] = a[j][k] - inv * a[i][k];
}
ret = ret * a[i][i];
}
return ret;
}
inline void IDFT(Complex *p) {
int i;
Complex tmp[3];
tmp[0] = p[0], tmp[1] = p[1], tmp[2] = p[2];
p[0] = tmp[0] + tmp[1] + tmp[2];
p[1] = tmp[0] + tmp[1] * invw[1] + tmp[2] * invw[2];
p[2] = tmp[0] + tmp[1] * invw[2] + tmp[2] * invw[1];
for (i = 0; i < 3; ++i) p[i] = p[i] * inv3;
}
inline int Calc(int p) {
int i, j, k;
Complex w0, w1, w2, c;
for (i = 0; i < 3; ++i) {
memset(a, 0, sizeof(a));
w0 = Complex(1, 0), w1 = w[i], w2 = w[(i + i) % 3];
for (j = 1; j <= m; ++j) {
k = ec[j] / bin[p] % 3;
c = (k == 1 ? w1 : (k == 2 ? w2 : w0));
a[eu[j]][eu[j]] = a[eu[j]][eu[j]] + c;
a[ev[j]][ev[j]] = a[ev[j]][ev[j]] + c;
a[eu[j]][ev[j]] = a[eu[j]][ev[j]] - c;
a[ev[j]][eu[j]] = a[ev[j]][eu[j]] - c;
}
coef[i] = Det();
}
IDFT(coef);
return (ll)Add(coef[1].a, Add(coef[2].a, coef[2].a)) * bin[p] % mod;
}
int main() {
int i, ans = 0;
scanf("%d%d", &n, &m);
w[0] = Complex(1, 0), w[1] = Complex(mod - inv2, (ll)rt3 * inv2 % mod);
w[2] = Complex(mod - inv2, mod - (ll)rt3 * inv2 % mod);
invw[0] = Complex(1, 0) / w[0], invw[1] = Complex(1, 0) / w[1], invw[2] = Complex(1, 0) / w[2];
for (i = 1; i <= m; ++i) scanf("%d%d%d", &eu[i], &ev[i], &ec[i]);
for (bin[0] = i = 1; i <= 10; ++i) bin[i] = bin[i - 1] * 3;
for (i = 0; i <= 10; ++i) Inc(ans, Calc(i));
printf("%d\n", ans);
return 0;
}
LOJ#6271. 「长乐集训 2017 Day10」生成树求和 加强版的更多相关文章
- loj6271 「长乐集训 2017 Day10」生成树求和 加强版(矩阵树定理,循环卷积)
loj6271 「长乐集训 2017 Day10」生成树求和 加强版(矩阵树定理,循环卷积) loj 题解时间 首先想到先分开三进制下每一位,然后每一位分别求结果为0,1,2的树的个数. 然后考虑矩阵 ...
- loj6271「长乐集训 2017 Day10」生成树求和 加强版
又是一个矩阵树套多项式的好题. 这里我们可以对每一位单独做矩阵树,但是矩阵树求的是边权积的和,而这里我们是要求加法,于是我们i将加法转化为多项式的乘法,其实这里相当于一个生成函数?之后如果我们暴力做的 ...
- 「长乐集训 2017 Day10」划分序列 (二分 dp)
「长乐集训 2017 Day10」划分序列 题目描述 给定一个长度为 n nn 的序列 Ai A_iAi,现在要求把这个序列分成恰好 K KK 段,(每一段是一个连续子序列,且每个元素恰好属于一 ...
- 「长乐集训 2017 Day1」区间 线段树
题目 对于两个区间\((a,b),(c,d)\),若\(c < a < d\)或\(c < b < d\)则可以从\((a,b)\)走到\((c,d)\)去,现在有以下两种操作 ...
- 「长乐集训 2017 Day8」修路 (斯坦纳树)
题目描述 村子间的小路年久失修,为了保障村子之间的往来,AAA君决定带领大家修路. 村子可以看做是一个边带权的无向图GGG, GGG 由 nnn 个点与 mmm 条边组成,图中的点从 1∼n1 \si ...
- Loj #2331. 「清华集训 2017」某位歌姬的故事
Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...
- Loj #2324. 「清华集训 2017」小 Y 和二叉树
Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...
- Loj #2321. 「清华集训 2017」无限之环
Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...
- Loj 2320.「清华集训 2017」生成树计数
Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...
随机推荐
- ReentrantLock锁的释放
一:代码 reentrantLock.unlock(); 虽然只有一句,但是源码却比较多: public final boolean release(int arg) { if (tryRelease ...
- template.js插件和ajax一起使用的例子
template.js 一款 JavaScript 模板引擎,简单,好用.提供一套模板语法,用户可以写一个模板区块,每次根据传入的数据,生成对应数据产生的HTML片段,渲染不同的效果. https:/ ...
- php引用使用不恰当而产生问题的地方
php变量的引用,如果使用的恰当,会带来效率的提升,相反,效率下降 $array = range(, ); $ref =& $array; var_dump(count($array)); / ...
- python多态和鸭子类型
多态与多态性 多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承). 比如:文件分为文本文件,可执行文件(在定义角度) 比如 我们按下 F1 键这个动作: 如果当前在 Fl ...
- 【GDOI2015】 推箱子 状态压缩+bfs
请注意$8$是一个美妙的数字 考虑到$8\times 8=64$,而一个unsigned long long是$64$位的,所以考虑用一个$01$状态存储箱子.考虑到箱子能转动,那么四种情况都存一下就 ...
- POJ 2250
#include <iostream> #include <stack> #define MAXN 150 #include <string> using name ...
- 《Head First 设计模式》读书笔记
目录 <Head First 设计模式>读书笔记 创建模式 结构模式 行为模式 用思维导图记录的读书笔记. <Head First 设计模式>读书笔记 模式的分类遵循<设 ...
- python 代码的缩进位置决定执行部分
通过近期的代码训练,我发现同样的一个语句,在同一行缩进的位置不同,决定的执行部分也不同.先给一个例子(我想打出1-100中的前20个偶数) 比较第一张图和第二张图.第一张截图实现了我想要的功能.可是当 ...
- 如何虚拟机里安装Win10操作系统
不多说,直接上干货! Windows Server 2003.2008.2012系统的安装 推荐网址:打开MSDN网站(http://msdn.itellyou.cn ) 关于给电脑换系统,很多人会花 ...
- win10系统自带的浏览器ME如何将网页转成PDF
不多说,直接上干货! 很多用户都已经开始玩上win10了,补充玩玩一些技巧,当作小灶. 不多废话,在windows 10网页是可以保存为pdf格式.具体如下: 欢迎大家,加入我的微信公众号:大数据躺过 ...