博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LOJ#6271. 「长乐集训 2017 Day10」生成树求和 加强版
阅读量:6429 次
发布时间:2019-06-23

本文共 3887 字,大约阅读时间需要 12 分钟。

由于是边权三进制不进位的相加,那么可以考虑每一位的贡献

对于每一位,生成树的边权相当于是做模 \(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 
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;}

转载于:https://www.cnblogs.com/cjoieryl/p/10322283.html

你可能感兴趣的文章
数据库设计三大范式
查看>>
ionic 字体的导入方法
查看>>
IP路由原理
查看>>
内部类详解
查看>>
洛谷P2726 阶乘 Factorials 数学
查看>>
类加载机制
查看>>
火柴棒等式(2008年NOIP全国联赛提高组)
查看>>
mongodb int型id 自增
查看>>
【转】关于大型网站技术演进的思考(十八)--网站静态化处理—反向代理(10)...
查看>>
Java中的4种代码块
查看>>
Ocelot(七)- 入门
查看>>
生成水杯热气
查看>>
程序员工作心法
查看>>
三个常用的PHP图表类库
查看>>
python中异常处理--raise的使用
查看>>
高中数学与初中数学的接轨点
查看>>
python 安装第三方模块
查看>>
Whitelabel Error Page 专题
查看>>
Spring Data Redis—Pub/Sub(附Web项目源码)
查看>>
RSD和wlwmanifest是什么
查看>>