将每一位拆开考虑,即不妨假设$0\le c<3$

考虑矩阵树定理,即统计所有生成树边权乘积的和,但我们这里要将边权相加,很明显将其作为幂次(如果作为$cx+1$无法对3取模)

更具体的,也就是将每一个位置从1变为$x^{c}$,系数对$10^{9}+7$取模,相乘时幂次对3取模

另外,高斯消元时需要对该多项式求逆,考虑$(ax^{2}+bx+c)^{-1}$即找到$dx^{2}+ex+f$满足
$$
(ax^{2}+bx+c)(dx^{2}+ex+f)\equiv 1(mod\ x^{3}-1)
$$
(幂次对3取模等价于原多项式对$x^{3}-1$取模,关于这个正确性不证明也没关系,可以将这个对$x^{3}-1$看作一个符号)

展开后,也就得到了如下的三元一次方程组
$$
\begin{cases}ad+bf+ce=0\\ ae+bd+cf=1\\af+be+cd=0\end{cases}
$$
通过一些计算,可以解得即
$$
\begin{cases}d=\frac{b^{2}-ac}{a^{3}+b^{3}+c^{3}-3abc}\\e=\frac{a^{2}-bc}{{a^{3}+b^{3}+c^{3}-3abc}}\\f=\frac{c^{2}-ab}{{a^{3}+b^{3}+c^{3}-3abc}}\end{cases}
$$
根据$a^{3}+b^{3}+c^{3}-3abc=\frac{(a+b+c)((a-b)^{2}+(b-c)^{2}+(c-a)^{2})}{2}$,若其为0其实与原来的0多项式是一样的,因此要判定要求$a\ne b$或$b\ne c$且$a+b+c\ne 0$($a+b+c\not\equiv 0(mod\ 10^{9}+7)$

更特别的,在如果最后一个式子不满足上述条件,则还要乘上去

由此计算即可,时间复杂度为$o(n^{3}\log_{3}c)$

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 105
4 #define mod 1000000007
5 struct Edge{
6 int x,y,z;
7 }e[N*N];
8 int n,m,ans;
9 int pow(int n,int m){
10 int s=n,ans=1;
11 while (m){
12 if (m&1)ans=1LL*ans*s%mod;
13 s=1LL*s*s%mod;
14 m>>=1;
15 }
16 return ans;
17 }
18 struct poly{
19 int a[3];
20 poly(){
21 a[0]=a[1]=a[2]=0;
22 }
23 void init(){
24 a[0]=a[1]=a[2]=0;
25 }
26 bool zero(){
27 return (a[0]==a[1])&&(a[1]==a[2])||((0LL+a[0]+a[1]+a[2])%mod==0);
28 }
29 poly operator + (const poly &k)const{
30 poly o;
31 for(int i=0;i<3;i++)o.a[i]=(a[i]+k.a[i])%mod;
32 return o;
33 }
34 poly operator - ()const{
35 poly o;
36 for(int i=0;i<3;i++)o.a[i]=(mod-a[i])%mod;
37 return o;
38 }
39 poly operator * (const poly &k)const{
40 poly o;
41 for(int i=0;i<3;i++)
42 for(int j=0;j<3;j++)o.a[(i+j)%3]=(o.a[(i+j)%3]+1LL*a[i]*k.a[j])%mod;
43 return o;
44 }
45 poly inv(){
46 int s=mod-3LL*a[0]*a[1]%mod*a[2]%mod;
47 for(int i=0;i<3;i++)s=(s+1LL*a[i]*a[i]%mod*a[i])%mod;
48 s=pow(s,mod-2);
49 poly o;
50 o.a[0]=(1LL*a[0]*a[0]-1LL*a[1]*a[2]%mod+mod)%mod*s%mod;
51 o.a[1]=(1LL*a[2]*a[2]-1LL*a[0]*a[1]%mod+mod)%mod*s%mod;
52 o.a[2]=(1LL*a[1]*a[1]-1LL*a[0]*a[2]%mod+mod)%mod*s%mod;
53 return o;
54 }
55 }a[N][N];
56 poly guess(){
57 poly ans;
58 ans.a[0]=1;
59 for(int i=1;i<n;i++){
60 int k=-1;
61 for(int j=i;j<n;j++)
62 if (!a[j][i].zero()){
63 k=j;
64 break;
65 }
66 if (k<0)return ans*a[i][i];
67 if (k!=i){
68 ans=(-ans);
69 for(int j=i;j<n;j++)swap(a[i][j],a[k][j]);
70 }
71 ans=ans*a[i][i];
72 for(int j=i+1;j<n;j++){
73 poly o=a[j][i]*a[i][i].inv();
74 for(int k=i;k<n;k++)a[j][k]=a[j][k]+(-o*a[i][k]);
75 }
76 }
77 return ans;
78 }
79 int main(){
80 freopen("sum.in","r",stdin);
81 freopen("sum.out","w",stdout);
82 scanf("%d%d",&n,&m);
83 for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
84 int s=1;
85 while (1){
86 bool flag=0;
87 for(int i=1;i<n;i++)
88 for(int j=1;j<n;j++)a[i][j].init();
89 for(int i=1;i<=m;i++){
90 poly o;
91 o.a[e[i].z%3]=1;
92 if (e[i].x<n)a[e[i].x][e[i].x]=a[e[i].x][e[i].x]+o;
93 if (e[i].y<n)a[e[i].y][e[i].y]=a[e[i].y][e[i].y]+o;
94 if ((e[i].x<n)&&(e[i].y<n)){
95 a[e[i].x][e[i].y]=a[e[i].x][e[i].y]+(-o);
96 a[e[i].y][e[i].x]=a[e[i].y][e[i].x]+(-o);
97 }
98 if (e[i].z)flag=1;
99 e[i].z/=3;
100 }
101 if (!flag)break;
102 poly o=guess();
103 ans=(ans+1LL*s*o.a[1]+2LL*s*o.a[2])%mod;
104 s=3LL*s%mod;
105 }
106 printf("%d",ans);
107 return 0;
108 }

[loj6271]生成树求和的更多相关文章

  1. loj6271 「长乐集训 2017 Day10」生成树求和 加强版(矩阵树定理,循环卷积)

    loj6271 「长乐集训 2017 Day10」生成树求和 加强版(矩阵树定理,循环卷积) loj 题解时间 首先想到先分开三进制下每一位,然后每一位分别求结果为0,1,2的树的个数. 然后考虑矩阵 ...

  2. 4.9 省选模拟赛 生成树求和 变元矩阵树定理 生成函数 iDFT 插值法

    有同学在loj上找到了加强版 所以这道题是可以交的.LINK:生成树求和 加强版 对于30分 爆搜 可实际上我爆搜只过了25分 有同学使用按秩合并并茶几的及时剪枝通过了30分. const int M ...

  3. loj6271「长乐集训 2017 Day10」生成树求和 加强版

    又是一个矩阵树套多项式的好题. 这里我们可以对每一位单独做矩阵树,但是矩阵树求的是边权积的和,而这里我们是要求加法,于是我们i将加法转化为多项式的乘法,其实这里相当于一个生成函数?之后如果我们暴力做的 ...

  4. LOJ#6271. 「长乐集训 2017 Day10」生成树求和 加强版

    传送门 由于是边权三进制不进位的相加,那么可以考虑每一位的贡献 对于每一位,生成树的边权相当于是做模 \(3\) 意义下的加法 考虑最后每一种边权的生成树个数,这个可以直接用生成函数,在矩阵树求解的时 ...

  5. 康复计划#5 Matrix-Tree定理(生成树计数)的另类证明和简单拓展

    本篇口胡写给我自己这样的什么都乱证一通的口胡选手 以及那些刚学Matrix-Tree,大致理解了常见的证明但还想看看有什么简单拓展的人- 大概讲一下我自己对Matrix-Tree定理的一些理解.常见版 ...

  6. uoj#335. 【清华集训2017】生成树计数(prufer序列+生成函数+多项式)

    传送门 好神仙的题目--又一次有了做一题学一堆的美好体验 据说本题有第二类斯特林数+分治\(FFT\)的做法,然而咱实在看不懂写的是啥,题解贴这里,有兴趣的可以自己去瞅瞅,看懂了记得回来跟咱讲讲 前置 ...

  7. POJ 2728 Desert King (最优比例生成树)

    POJ2728 无向图中对每条边i 有两个权值wi 和vi 求一个生成树使得 (w1+w2+...wn-1)/(v1+v2+...+vn-1)最小. 采用二分答案mid的思想. 将边的权值改为 wi- ...

  8. [CSP-S模拟测试]:小P的生成树(数学+Kruskal)

    题目描述 小$P$是个勤于思考的好孩子,自从学习了最大生成树后,他就一直在想:能否将边权范围从实数推广到复数呢?可是马上小$P$就发现了问题,复数之间的大小关系并没有定义.于是对于任意两个复数$z_1 ...

  9. Java程序:从命令行接收多个数字,求和并输出结果

    一.设计思想:由于命令行接收的是字符串类型,因此应先将字符串类型转化为整型或其他字符型,然后利用for循环求和并输出结果 二.程序流程图: 三.源程序代码:   //王荣荣 2016/9/23     ...

随机推荐

  1. javascriptRemke之深入迭代

    javascriptRemke之深入迭代 前言:"迭代"意为按照顺序反复多次执行一段程序,ECMAscript6中新增了两个高级特性:迭代器与生成器,使用这两个特性能更高效地实现迭 ...

  2. 题解 HDU 5279 YJC plays Minecraft

    题目传送门 题目大意 给出\(n\)以及\(a_{1,2,...,n}\),表示有\(n\)个完全图,第\(i\)个完全图大小为\(a_i\),这些完全图之间第\(i\)个完全图的点\(a_i\)与\ ...

  3. pip 安装软件报 Requirement already satisfied

    pip 安装的时候报错了,以为是豆瓣源有问题,换了还是一样,于是我们只需要加入一个参数 --target=路径    给它一个指定的位置就可以解决这个问题 安装位置不变,只是增加了一个参数在后面

  4. noj -> 跳马

    00 题目 描述: 在国际象棋中,马的走法与中车象棋类似,即俗话说的"马走日",下图所示即国际象棋中马(K)在一步能到达的格子(其中黑色的格子是能到达的位置). 现有一200*20 ...

  5. ShardingJdbc基于Zookeeper实现分布式治理

    随着数据规模的不断膨胀,使用多节点集群的分布式方式逐渐成为趋势.在这种情况下,如何高效.自动化管理集群节点,实现不同节点的协同工作,配置一致性,状态一致性,高可用性,可观测性等,就成为一个重要的挑战. ...

  6. [Java]Sevlet

    0 前言 对于Java程序员而言,Web服务器(如Tomcat)是后端开发绕不过去的坎.简单来看,浏览器发送HTTP请求给服务器,服务器处理后发送HTTP响应给浏览器. Web服务器负责对请求进行处理 ...

  7. JVM:内存溢出OOM

    JVM:内存溢出OOM 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 经典错误 JVM 中常见的两个 OOM 错误 StackoverflowError:栈溢出 ...

  8. 2021.7.15考试总结[NOIP模拟16]

    ZJ模拟D2就是NB.. T1 Star Way To Heaven 谁能想到这竟是个最小生成树呢?(T1挂分100的高人JYF就在我身边 把上边界和下边界看成一个点和星星跑最小生成树,从上边界开始跑 ...

  9. 转:Modelsim和Vcs+Verdi使用技巧(Linux)

    Modelsim脚本自动仿真 1.创建文件 run.do,"#"为注释符号 quit -sim #退出上次仿真 .main clear #清除上次仿真所有文件以及打印信息 vlib ...

  10. Python pip 和pip3区别 联系

    python 有python2和python3的区别 那么pip也有pip和pip3的区别 大概是这样的 pip是python的包管理工具,pip和pip3版本不同,都位于Scripts\目录下: 如 ...