[BZOJ1494] [NOI2007]生成树计数

Description

最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现:·n个结点的环的生成树个数为n。·n个结点的完全图的生成树个数为n^(n-2)。这两个发现让小栋欣喜若狂,由此更加坚定了

他继续计算生成树个数的想法,他要计算出各种各样图的生成树数目。一天,小栋和同学聚会,大家围坐在一张大圆桌周围。小栋看了看,马上想到了生成树问题。

如果把每个同学看成一个结点,邻座(结点间距离为1)的同学间连一条边,就变成了一个环。可是,小栋对环的计数已经十分娴熟且不再感兴趣。于是,小栋又把图变了一下:不仅把邻座的同学之间连

一条边,还把相隔一个座位(结点间距离为2)的同学之间也连一条边,将结点间有边直接相连的这两种情况统称为有边相连。



如图1所示。小栋以前没有计算过这类图的生成树个数,但是,他想起了老师讲过的计算任意图的生成树个数的一种通用方法:构造一个n×n的矩阵A={aij},其中其中di表示结点i的度数。与图1相应的A

矩阵如下所示。为了计算图1所对应的生成数的个数,只要去掉矩阵A的最后一行和最后一列,得到一个(n-1)×(n-1)的矩阵B,计算出矩阵B的行列式的值便可得到图1的生成树的个数所以生成树的个数为

|B|=3528。小栋发现利用通用方法,因计算过于复杂而很难算出来,而且用其他方法也难以找到更简便的公式进行计算。于是,他将图做了简化,从一个地方将圆桌断开,这样所有的同学形成了一条链

,连接距离为1和距离为2的点。例如八个点的情形如下:这样生成树的总数就减少了很多。小栋不停的思考,一直到聚会结束,终于找到了一种快捷的方法计算出这个图的生成树个数。可是,如果把距

离为3的点也连起来,小栋就不知道如何快捷计算了。现在,请你帮助小栋计算这类图的生成树的数目。

Input

包含两个整数k,n,由一个空格分隔。k表示要将所有距离不超过k(含k)的结点连接起来,n表示有n个结点。

Output

输出一个整数,表示生成树的个数。由于答案可能比较大,所以你 只要输出答案除65521 的余数即可。

Sample Input

3 5

Sample Output

75

试题分析

发现k很小,所以可以用最小表示法表示前k个点加上k+1个点的连通性,然后因为m比较大所以需要矩阵快速幂。

代码比较挫,在此理一下思路:

  • 把所有最小表示法预处理,并算出每个联通情况的总数。
  • 考虑每一个状态加上一个点枚举连边情况,并判断:无环,第一个点(会被删掉的)是否已经与后面还会考虑的某一个联通。
  • 加入连通性的时候转化为最小表示法。
  • 矩阵快速幂。
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<vector>
  5. #include<algorithm>
  6. using namespace std;
  7. #define LL long long
  8. inline LL read(){
  9. LL x=0,f=1; char c=getchar();
  10. for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  11. for(;isdigit(c);c=getchar()) x=x*10+c-'0';
  12. return x*f;
  13. }
  14. const LL INF = 2147483600;
  15. const LL MAXN = 100010;
  16. const LL Mod = 65521;
  17. LL N,M;
  18. struct Mat{
  19. LL x,y; LL a[101][101];
  20. inline void init(LL rr,LL cc){x=rr; y=cc; memset(a,0,sizeof(a));}
  21. }A,Ans; LL Pw[11]; LL sta[101],top;
  22. Mat operator * (Mat A,Mat B){
  23. Mat C; C.init(A.x,B.y);
  24. for(LL i=1;i<=A.x;i++){
  25. for(LL j=1;j<=B.y;j++){
  26. for(LL k=1;k<=A.y;k++)
  27. C.a[i][j]+=A.a[i][k]*B.a[k][j]%Mod,C.a[i][j]%=Mod;
  28. }
  29. } return C;
  30. }
  31. Mat operator ^ (Mat A,LL P){
  32. Mat B; B.init(A.x,A.y); for(LL i=0;i<=A.x;i++) B.a[i][i]=1;
  33. for(; P ; P>>=1,A=A*A) if(P&1) B=A*B; return B;
  34. }
  35. inline LL Pow(LL A,LL B){
  36. LL res = 1; for(; B ; B>>=1,A=A*A%Mod) if(B&1) res=res*A%Mod; return res;
  37. } LL Pos[MAXN+1];
  38. inline void Get_state(LL k){
  39. for(LL i=0;i<=top;i++) sta[i]=0;
  40. top=0; while(k){
  41. sta[++top]=k%10,k/=10;
  42. } while(top<N) sta[top+1]=0,++top; reverse(sta+1,sta+N+1); return ;
  43. } LL cnt; LL state[MAXN+1][11]; LL vis[13];
  44. inline void Add(LL k){
  45. Get_state(k); memset(vis,0,sizeof(vis)); LL now=0;
  46. for(LL i=1;i<=N;i++){
  47. if(!vis[sta[i]]) ++now; vis[sta[i]]++;
  48. if(now-1<sta[i]) return ;
  49. } ++cnt; LL res=1; Pos[k]=cnt;
  50. for(LL i=0;i<=N;i++){
  51. state[cnt][i]=sta[i];
  52. if(vis[i]>1) res=res*Pow(vis[i],vis[i]-2)%Mod;
  53. } Ans.a[1][cnt]=res;return ;
  54. } bool ald[MAXN+1]; LL fa[MAXN+1];
  55. LL find(LL x){
  56. return (x==fa[x]?x:(fa[x]=find(fa[x])));
  57. }
  58. inline LL GS(){
  59. for(LL i=0;i<10;i++) vis[i]=-1; LL now=0,id=0;
  60. for(LL i=2;i<=N+1;i++){
  61. LL x=find(i);
  62. if(vis[x]==-1){
  63. vis[x]=now; id=id*10+now; ++now;
  64. } else id=id*10+vis[x];
  65. }
  66. return Pos[id];
  67. }
  68. inline void Add(LL k,LL add_state){
  69. for(LL i=0;i<=N+1;i++) fa[i]=i;
  70. for(LL i=1;i<=N;i++){
  71. for(LL j=i+1;j<=N;j++){
  72. if(state[k][i]==state[k][j]){
  73. //cout<<"here\n";
  74. LL xx=find(i),yy=find(j);
  75. //cout<<xx<<" "<<yy<<endl;
  76. if(xx!=yy) fa[yy]=xx;
  77. }
  78. }
  79. }
  80. for(LL i=1;i<=N;i++){
  81. if(add_state&(1<<(i-1))){
  82. LL xx=find(N+1),yy=find(i);
  83. if(xx==yy) return ;
  84. fa[yy]=xx;
  85. }
  86. } bool flag=false;
  87. for(LL i=2;i<=N+1;i++){
  88. if(find(1)==find(i)) {flag=true; break;}
  89. } if(!flag) return ;
  90. A.a[k][GS()]++;
  91. }
  92. inline void init_state(LL k){
  93. for(LL i=0;i<(1<<N);i++) Add(k,i); return ;
  94. }
  95. int main(){
  96. //freopen(".in","r",stdin);
  97. //freopen(".out","w",stdout);
  98. N=read(),M=read(); Pw[0]=1;
  99. for(LL i=1;i<=N;i++) Pw[i]=Pw[i-1]*10;
  100. for(LL i=0;i<=43210;i++) if(!ald[i%Pw[N]]) Add(i),ald[i%Pw[N]]=true;
  101. A.init(cnt,cnt); Ans.x=1; Ans.y=cnt;
  102. for(LL i=1;i<=cnt;i++) init_state(i);
  103. A=A^(M-N);
  104. Ans=Ans*A; printf("%lld\n",Ans.a[1][1]%Mod);
  105. return 0;
  106. }

[BZOJ1494]生成树计数的更多相关文章

  1. bzoj1494 生成树计数 (dp+矩阵快速幂)

    题面欺诈系列... 因为一个点最多只能连到前k个点,所以只有当前的连续k个点的连通情况是对接下来的求解有用的 那么就可以计算k个点的所有连通情况,dfs以下发现k=5的时候有52种. 我们把它们用类似 ...

  2. 【BZOJ1494】【NOI2007】生成树计数(动态规划,矩阵快速幂)

    [BZOJ1494][NOI2007]生成树计数(动态规划,矩阵快速幂) 题面 Description 最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现: ·n个结点的环的生成树个数为 ...

  3. BZOJ1494 [NOI2007]生成树计数

    题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser  autoint Logout 捐赠本站 Probl ...

  4. [BZOJ1494][NOI2007]生成树计数 状压dp 并查集

    1494: [NOI2007]生成树计数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 793  Solved: 451[Submit][Status][ ...

  5. 【BZOJ1002】【FJOI2007】轮状病毒(生成树计数)

    1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1766  Solved: 946[Submit][Status ...

  6. SPOJ 104 HIGH - Highways 生成树计数

    题目链接:https://vjudge.net/problem/SPOJ-HIGH 解法: 生成树计数 1.构造 基尔霍夫矩阵(又叫拉普拉斯矩阵) n阶矩阵 若u.v之间有边相连 C[u][v]=C[ ...

  7. Luogu P5296 [北京省选集训2019]生成树计数

    Luogu P5296 [北京省选集训2019]生成树计数 题目链接 题目大意:给定每条边的边权.一颗生成树的权值为边权和的\(k\)次方.求出所有生成树的权值和. 我们列出答案的式子: 设\(E\) ...

  8. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  9. 「UVA10766」Organising the Organisation(生成树计数)

    BUPT 2017 Summer Training (for 16) #6C 题意 n个点,完全图减去m条边,求生成树个数. 题解 注意可能会给重边. 然后就是生成树计数了. 代码 #include ...

随机推荐

  1. Brave Game HDU1846(巴什博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1846 题目: Problem Description 十年前读大学的时候,中国每年都要从国外引进一些电 ...

  2. HDU 1465 不容易系列之一 (错排公式+容斥)

    题目链接 Problem Description 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了! 做好"一件"事情尚且不易,若想永远成功而总从不失败,那更是难上 ...

  3. k8s取节点内docker中的日志

    Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg).在Docker技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提高了大 ...

  4. android CVE 漏洞汇总

    arm exploits 技术教程: Learning Pentesting for Android Devices CVE-2015-1530 ,CVE-2015-1474 两个android整数溢 ...

  5. Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)【转】

    转自:http://www.linuxidc.com/Linux/2013-06/85221p3.htm 阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入 ...

  6. Load balancer does not have available server for client:xxx

    今天在搭建一个springcloud项目在搭建以zuul为网关的时候,项目抛了一个异常, com.netflix.zuul.exception.ZuulException: Forwarding er ...

  7. Web开发中,页面渲染方案

    转载自:http://www.jianshu.com/p/d1d29e97f6b8 (在该文章中看到一段感兴趣的文字,转载过来) 在Web开发中,有两种主流的页面渲染方案: 服务器端渲染,通过页面渲染 ...

  8. 其实linux下远程windows并不麻烦

    1:如果你是安装的ubuntu.那么安装完成之后就自带一个Remmina的远程桌面工具 2:这里我们需要安装rdesktop和tsclient,其中rdesktop是基于命令行的工具,tsclient ...

  9. leetcode 之Single Number(13)

    看见这题我的第一反应是用哈希来做,不过更简洁的做法是用异或来处理,只要是偶数个都为0(0和任意数异或仍为数本身). int singleNumber(int A[], int n) { ; ; i & ...

  10. 5:django 常用函数

    用django写view函数的时候,我们常常用到django.shortcuts里面的很多常用函数, 这节我们来看看这些函数的具体用法吧 render render(request, template ...