正题

题目链接:https://ac.nowcoder.com/acm/contest/161/F


题目大意

给出\(n\)个点的一张图,求它的所有生成树中权值和为\(k\)的倍数的个数。输出答案对\(p\)取模

\(1\leq n,k\leq 100,1\leq m\leq 10^4,p\in[2,10^9]\cup Pri\)

数据保证\(k\equiv 1(mod\ p)\)


解题思路

一个想法是把一条边权看做\(x^w\)的多项式,用矩阵树定理乘起来后\(k\)的倍数的系数和就是答案。

但是这样系数是\(nk\)个,显然搞不定。

类似于CF917D-StrangerTree的做法我们可以带入若干个值然后跑矩阵数之后求出若干个点值。

但是这里是\(k\)的倍数,我们要模拟卷积,可以带入\(k\)个\(g\)满足\(g^k=1\)的就可以了。

这里保证了\(k\equiv 1(mod\ p)\),所以我们求出\(p\)的原根\(g\)然后带入\(g^{\frac{p-1}{k}\times i}(i\in[0,k-1])\)就可以了。

然后直接拉插求出\(x=0\)的点值就好了。

时间复杂度\(O(n^3k)\)


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. #define ll long long
  6. using namespace std;
  7. const ll N=110;
  8. struct node{
  9. ll x,y,w;
  10. }e[N*N];
  11. ll n,m,k,P,g,x[N],y[N];
  12. vector<ll> p;
  13. ll power(ll x,ll b){
  14. ll ans=1;
  15. while(b){
  16. if(b&1)ans=ans*x%P;
  17. x=x*x%P;b>>=1;
  18. }
  19. return ans;
  20. }
  21. void Prime(){
  22. ll x=P-1;
  23. for(ll i=2;i*i<=x;i++)
  24. if(x%i==0){
  25. p.push_back(i);
  26. while(x%i==0)x/=i;
  27. }
  28. if(x>1)p.push_back(x);
  29. }
  30. bool check(ll x){
  31. for(ll i=0;i<p.size();i++)
  32. if(power(x,(P-1)/p[i])==1)return 0;
  33. return 1;
  34. }
  35. namespace Matrix{
  36. ll a[N][N];
  37. ll det(ll v){
  38. memset(a,0,sizeof(a));
  39. ll ans=1;
  40. for(ll i=1;i<=m;i++){
  41. ll x=e[i].x,y=e[i].y,w=power(v,e[i].w);
  42. (a[x][y]+=P-w)%=P;(a[y][x]+=P-w)%=P;
  43. (a[x][x]+=w)%=P;(a[y][y]+=w)%=P;
  44. }
  45. ll f=0;
  46. for(ll i=1;i<n;i++){
  47. for(ll j=i;j<n;j++)
  48. if(a[j][i]){
  49. if(i==j)break;
  50. swap(a[i],a[j]);
  51. f^=1;break;
  52. }
  53. ans=ans*a[i][i]%P;
  54. ll inv=power(a[i][i],P-2);
  55. for(ll j=i;j<n;j++)a[i][j]=a[i][j]*inv%P;
  56. for(ll j=i+1;j<n;j++){
  57. ll rate=P-a[j][i];
  58. for(ll k=i;k<n;k++)
  59. (a[j][k]+=rate*a[i][k])%=P;
  60. }
  61. }
  62. return f?(P-ans):ans;
  63. }
  64. }
  65. signed main()
  66. {
  67. scanf("%lld%lld%lld%lld",&n,&m,&k,&P);
  68. Prime();g=1;
  69. while(!check(g))
  70. g++;
  71. for(ll i=1;i<=m;i++)
  72. scanf("%lld%lld%lld",&e[i].x,&e[i].y,&e[i].w);
  73. for(ll i=1;i<=k;i++){
  74. x[i]=power(g,(P-1)/k*(i-1));
  75. y[i]=Matrix::det(x[i]);
  76. }
  77. ll ans=0;
  78. for(ll i=1;i<=k;i++){
  79. ll tmp=1;
  80. for(ll j=1;j<=k;j++)
  81. if(i!=j)tmp=tmp*(P-x[j])%P*power(x[i]-x[j],P-2)%P;
  82. (ans+=tmp*y[i]%P)%=P;
  83. }
  84. printf("%lld\n",(ans+P)%P);
  85. return 0;
  86. }

Wannafly挑战赛23F-计数【原根,矩阵树定理,拉格朗日插值】的更多相关文章

  1. 牛客Wannafly挑战赛23F 计数(循环卷积+拉格朗日插值/单位根反演)

    传送门 直接的想法就是设 \(x^k\) 为边权,矩阵树定理一波后取出 \(x^{nk}\) 的系数即可 也就是求出模 \(x^k\) 意义下的循环卷积的常数项 考虑插值出最后多项式,类比 \(DFT ...

  2. bzoj1016 [JSOI2008]最小生成树计数——Kruskal+矩阵树定理

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 从 Kruskal 算法的过程来考虑产生多种方案的原因,就是边权相同的边有一样的功能, ...

  3. BZOJ 1016 最小生成树计数(矩阵树定理)

    我们把边从小到大排序,然后依次插入一种权值的边,然后把每一个联通块合并. 然后当一次插入的边不止一条时做矩阵树定理就行了.算出有多少种生成树就行了. 剩下的交给乘法原理. 实现一不小心就会让程序变得很 ...

  4. 洛谷4208 JSOI2008最小生成树计数(矩阵树定理+高斯消元)

    qwq 这个题目真的是很好的一个题啊 qwq 其实一开始想这个题,肯定是无从下手. 首先,我们会发现,对于无向图的一个最小生成树来说,只有当存在一些边与内部的某些边权值相同的时候且能等效替代的时候,才 ...

  5. [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)

    In some countries building highways takes a lot of time... Maybe that's because there are many possi ...

  6. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  7. spoj104 highways 生成树计数(矩阵树定理)

    https://blog.csdn.net/zhaoruixiang1111/article/details/79185927 为了学一个矩阵树定理 从行列式开始学(就当提前学线代了.. 论文生成树的 ...

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

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

  9. CSU 1805 Three Capitals(矩阵树定理+Best定理)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1805 题意: A和B之间有a条边,A和G之间有b条边,B和G之间有c条边.现在从A点出发走遍所 ...

随机推荐

  1. Rabbit-用户上线接收消息

    application-dev.yml spring: rabbitmq: username: admin password: admin host: 192.168.0.45 port: 5672 ...

  2. C#多线程---Semaphore实现线程同步

    一.简介 Semaphore类限制可同时访问某一资源或资源池的线程数.线程通过调用 WaitOne方法将信号量减1,并通过调用 Release方法把信号量加1. 构造函数:public Semapho ...

  3. 二 MongoDB数据类型和$type操作符

    一.MongoDB中可以使用的类型如下表所示 二.$type操作符 举个例子:想获取指定集合中title为String类型的所有文档

  4. git撤销已经push到远程仓库上的代码

    具体方法,git命令:git reset --hard <commit_id>git push origin HEAD --force commit_id可以通过git命令:git log ...

  5. 翻译Go Blog: 常量

    常量 Pob Pike 2014年8月24日 原文 介绍 Go是一门静态语言,它不允许不同数字类型间的操作.你不能将一个浮点数(float64)和一个整数(int)相加,也不能将一个32位整数(int ...

  6. 高德渲染网关Go语言重构实践

    ​1.导读 高德启动Go业务建设已经有段时间了,主要包含Go应用落地,Go中间件建设,云原生三个部分.经过持续的发力,在这些方面取得了不错的进展.高德Go业务落地过程是如何实现的,遇到过哪些问题,如何 ...

  7. Servlet过滤器----Filter

    JavaEE的Servlet规范描述了三种技术:Servlet,Filter,Listener (一)过滤器简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过F ...

  8. (一)羽夏看C语言——简述

    "羽夏看C语言"介绍什么   本系列从汇编的角度,比较翔实的介绍C语言.C++和C其实是一样的东西,C++的编译器只是更强大,更能帮助我们写代码,例如模板.没有特殊说明,本系列不会 ...

  9. 泛微OA E-cology(CNVD-2019-32204)远程命令执行漏洞复现分析

    漏洞复现 影响版本: E-cology 7.0 E-cology 8.0 E-cology 8.1 E-cology 9.0   直接在网站根目录后加入组件访问路径 /weaver/bsh.servl ...

  10. vue开发流程

    在安装node.js 测试安装  在cmd 下输入node   如查能正确输出命令提示符,表明安装好node 测试安装npm -v   如果能成功出现版本信息表示安装好npm 安装配置 G码云   或 ...