题目大意

​  有一个\(n\)个点\(m\)条边的图,每条边有一种颜色\(c_i\in\{1,2,3\}\),求所有的包括\(i\)条颜色为\(1\)的边,\(j\)条颜色为\(2\)的边,\(k\)条颜色为\(3\)的边的生成树的数量。

​  对\({10}^9+7\)取模。

​  \(n\leq 50\)

题解

​  如果\(\forall i,c_i=1\),就可以直接用基尔霍夫矩阵计算生成树个数。但是现在有三种颜色,不妨设\(c_i=2\)的边的边权为\(x\),\(c_i=3\)的边的边权为\(y\)。因为\(x\)的次数不会超过\(n-1\),所以可以设\(y=x^n\)。基尔霍夫矩阵可能是这样子的:

​ $$\begin{bmatrix}1+x&-1&-x\-1&1+xn&-xn\-x&-xn&x{n+1}\end{bmatrix}$$

​  这样的话直接高斯消元很明显会TLE,可以用FFT优化。FFT是在每次乘法时先做一次求值,做一次点值乘法,最后做一次插值。所以我们可以先在消元前做一次求值,消元时直接做点值乘法,最后再插值插回来。

​  因为答案的最高次不超过\(n(n-1)\),所以我们可以把\(n(n-1)+1\)个点带到行列式中,把每次得到的行列式保存下来,最后再用拉格朗日插值插回来。这里不能用高斯消元是因为高斯消元会直接TLE。

​  求行列式的总时间复杂度是\(O(n^2)\times O(n^3)=O(n^5)\),拉格朗日插值的时间复杂度是\(O({(n^2)}^2)=O(n^4)\),高斯消元的时间复杂度是\(O({(n^2)}^3)=O(n^6)\)。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
ll p=1000000007;
ll a[60][60];
int lx[10010];
int ly[10010];
int lc[10010];
ll x[3010];
ll y[3010];
ll c[3010];
ll b[3010];
ll d[3010];
ll l[3010];
ll ans[3010];
ll fp(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
s=s*a%p;
a=a*a%p;
b>>=1;
}
return s;
}
ll calc(int t)
{
int i,j,k;
ll s=1;
for(i=1;i<=t;i++)
{
for(j=i;j<=t;j++)
if(a[j][i])
break;
if(j>t)
return 0;
int x=j;
if(x>i)
{
s=-s;
for(j=i;j<=t;j++)
swap(a[i][j],a[x][j]);
}
for(j=i+1;j<=t;j++)
if(a[j][i])
{
ll d=a[j][i]*fp(a[i][i],p-2)%p;
for(k=i;k<=t;k++)
a[j][k]=(a[j][k]-a[i][k]*d%p)%p;
}
}
for(i=1;i<=t;i++)
s=s*a[i][i]%p;
s=(s+p)%p;
return s;
}
int main()
{
// freopen("count.in","r",stdin);
int n,m;
scanf("%d%d",&n,&m);
int i,j,k;
for(i=1;i<=m;i++)
scanf("%d%d%d",&lx[i],&ly[i],&lc[i]);
for(i=1;i<=n*n;i++)
{
x[i]=(i*1000+1)%p;
// x[i]=i%p;
ll px=fp(x[i],n);
memset(a,0,sizeof a);
for(j=1;j<=m;j++)
{
if(lc[j]==1)
{
a[lx[j]][lx[j]]++;
a[ly[j]][ly[j]]++;
a[lx[j]][ly[j]]--;
a[ly[j]][lx[j]]--;
}
else if(lc[j]==2)
{
(a[lx[j]][lx[j]]+=x[i])%=p;
(a[ly[j]][ly[j]]+=x[i])%=p;
(a[lx[j]][ly[j]]-=x[i])%=p;
(a[ly[j]][lx[j]]-=x[i])%=p;
}
else
{
(a[lx[j]][lx[j]]+=px)%=p;
(a[ly[j]][ly[j]]+=px)%=p;
(a[lx[j]][ly[j]]-=px)%=p;
(a[ly[j]][lx[j]]-=px)%=p;
}
}
y[i]=calc(n-1);
}
int t=n*n;
memset(c,0,sizeof c);
c[0]=1;
memset(ans,0,sizeof ans);
for(i=1;i<=t;i++)
for(j=t;j>=0;j--)
{
(c[j+1]+=c[j])%=p;
(c[j]=-c[j]*x[i])%=p;
}
for(i=1;i<=t;i++)
{
memcpy(d,c,sizeof d);
memset(b,0,sizeof b);
for(j=t;j>=0;j--)
{
b[j]=d[j+1];
d[j]=(d[j]+d[j+1]*x[i])%p;
d[j+1]=0;
}
ll s=0,px=1;
for(j=0;j<=t;j++)
{
s=(s+px*b[j])%p;
px=px*x[i]%p;
}
s=fp(s,p-2)*y[i]%p;
for(j=0;j<=t;j++)
b[j]=b[j]*s%p;
for(j=0;j<=t;j++)
ans[j]=(ans[j]+b[j])%p;
}
for(i=0;i<n;i++)
for(j=0;j<n-i;j++)
printf("%lld\n",(ans[j+n*(n-i-j-1)]%p+p)%p);
return 0;
}

【XSY1537】五颜六色的幻想乡 数学 生成树计数 拉格朗日插值的更多相关文章

  1. 幻想乡三连A:五颜六色的幻想乡

    非常直接地构造 由于答案与生成树计数有关,所以一定要使用矩阵树定理,但这样就不能限制每种颜色的便使用的数量 我们构造$N^2$个关于$Ans_{x,y}$的方程,枚举将红色的边拆成$x$条,将蓝色的边 ...

  2. 【XSY1538】连在一起的幻想乡 数学 无向连通图计数

    题目大意 ​ 给你\(n,p\),求\(n\)个点组成的所有无向连通图的边数的平方和模\(p\) ​ \(n\leq 2000,p\leq {10}^9\) 题解 ​ 设\(m=\frac{n(n-1 ...

  3. [2016北京集训试题8]连在一起的幻想乡[dp+无向图计数]

    Description Solution 本博客参考yww大佬的博客,为了加深理解我就自己再写一遍啦. 以下的“无向图”均无重边无自环. 定义f0[n]为n个点构成的无向图个数,f1[n]为n个点构成 ...

  4. luogu P4948 数列求和 推式子 简单数学推导 二项式 拉格朗日插值

    LINK:数列求和 每次遇到这种题目都不太会写.但是做法很简单. 终有一天我会成功的. 考虑类似等比数列求和的东西 帽子戏法一下. 设\(f(k)=\sum_{i=1}^ni^ka^i\) 考虑\(a ...

  5. 生成树计数 Matrix-Tree 定理 学习笔记

    一直都知道要用Matrix-Tree定理来解决生成树计数问题,但是拖到今天才来学.博主数学不好也只能跟着各位大佬博客学一下它的应用以及会做题,证明实在是不会. 推荐博客: https://www.cn ...

  6. 「SHOI2016」黑暗前的幻想乡 解题报告

    「SHOI2016」黑暗前的幻想乡 sb题想不出来,应该去思考原因,而不是自暴自弃 一开始总是想着对子树做dp,但是状态压不起去,考虑用容斥消减一些条件变得好统计,结果越想越乱. 期间想过矩阵树定理, ...

  7. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

  8. [ZJOI2015]地震后的幻想乡(期望+dp)

    题目描述 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任务是尽快让幻想 ...

  9. P4336 [SHOI2016]黑暗前的幻想乡

    P4336 [SHOI2016]黑暗前的幻想乡 矩阵树定理(高斯消元+乘法逆元)+容斥 ans=总方案数 -(公司1未参加方案数 ∪ 公司2未参加方案数 ∪ 公司3未参加方案数 ∪ ...... ∪ ...

随机推荐

  1. Beta阶段团队成员贡献分分配规则

    Beta阶段团队成员贡献分分配规则 Alpha阶段贡献分分配有些负责,在这里进行一些修改: 对任务完成得分部分进行了简化 对发现bug的惩罚措施进行了修改 移除了优化得分,不鼓励修改他人代码 移除了帮 ...

  2. Python-常见面试题-持续更新

    1.请你简要介绍一下Python的生成器是什么 答:Python生成器是一个返回可以迭代对象的函数,可以被用作控制循环的迭代行为. 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用 ...

  3. hdu 5584 LCM Walk

    没用运用好式子...想想其实很简单,首先应该分析,由于每次加一个LCM是大于等于其中任何一个数的,那么我LCM加在哪个数上面,那个数就是会变成大的,这样想,我们就知道,每个(x,y)对应就一种情况. ...

  4. Vladik and Favorite Game CodeForces - 811D (思维+BFS+模拟+交互题)

    D. Vladik and Favorite Game time limit per test 2 seconds memory limit per test 256 megabytes input ...

  5. 同步和异步概念(由DZW前端框架引发的百度地图api无法加载问题总结)

    首先概念: 在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去:异步是指进程不需要一直等下去,而是继续 ...

  6. awk+sed编程

  7. 课程存储校对:程序设计思想、源程序代码、运行结果截图,以及开发过程中的项目计划日志、时间记录日志、缺陷记录日志(PSP0级记录)。

    1.程序设计思想 ⑴将JDBC驱动jar包导入到WEB-INF的lib文件夹下 ⑵建立数据库,在数据库中建表,分别将课程名称.任课教师及上课地点录入到列中 ⑶首先写出加载驱动.关闭资源的工具类和异常处 ...

  8. asp.net core认证和授权的初始认识--claim、claimsidentity、claimsprincipal

    Claim表示一个声明单元,它用来组成ClaimsIdentity.ClaimsIdentity表示一个证件,例如身份证,身份证上面的名字表示一个Claim,身份证号也表示一个Claim,所有这些Cl ...

  9. Oracle 同义词(Synonym)

    同义词(Synonym)是表.索引.视图等模式对象的一个别名.通过模式对象创建同义词,可以隐藏对象的实际名称和所有者信息,隐藏分布式数据库中远程对象的设置信息,由此为对象提提供一定的安全性保证.同义词 ...

  10. [转帖]SAP一句话入门:Sales and Distribution

    SAP一句话入门:Sales and Distribution http://blog.vsharing.com/MilesForce/A616565.html SD是Sales and Distri ...