题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1494

sol  :前排膜拜http://blog.csdn.net/qpswwww/article/details/45362639

   虽然dalao们说了一些最小表示法啊什么k=5时只有52种状态啊balabala,然而我并不会.......

   因为k很小,可以考虑用状压来记录联通块信息,考虑dp

   dp[i][j]表示前i个点,最后k个点联通情况为j时的方案数

   由于n很大,考虑采用矩阵快速幂优化,用并查集判环&维护

   那么最终可以构造函数f[x][y]表示状态x向状态y转移有多少种合法的连接方式

   初始函数g[x]是一个行向量,每个位置代表一个初始状态

   这样就可以做了........最后输出A[1][1]即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int Mx=;
const int p=;
using namespace std;
ll n;
int K,tot/*状态总数*/,Tr_siz[]={,,,,,}/*完全图的生成树个数*/;
int fa[Mx],siz[Mx]/*第i个联通块的大小*/,status[],hash[<<]/*hash[S]=状态S的编号*/; struct Matrix
{
int n,m; ll num[Mx][Mx];
Matrix() { n=m=; memset(num,,sizeof(num)); }
}A,trans;
Matrix operator*(Matrix a,Matrix b)
{
Matrix c;
c.n=a.n,c.m=b.m;
for(int k=;k<=a.m;k++)
for(int i=;i<=c.n;i++)
for(int j=;j<=c.m;j++)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%p)%p;
return c;
}
void Pow(ll c)
{
while(c)
{
if(c&) A=A*trans;
trans=trans*trans;
c>>=;
}
} void dfs(int x,int sta) //当前要加入第x个点的联通状态,当前的状态为sta
{
if(x==K+)
{
memset(siz,,sizeof(siz));
A.num[][++tot]=;
for(int i=;i<=K;i++)
siz[sta>>((i-)*)&]++;
for(int i=;i<K;i++)
A.num[][tot]*=Tr_siz[siz[i]];
status[tot]=sta;
hash[sta]=tot;
return;
}
int tmp=-; //联通块的最大编号,联通块编号的区间是[0,K-1]
for(int i=;i<x;i++) //!!!当前的sta里只保存了1~pos-1这些点的连通性
tmp=max(tmp,sta>>((i-)*)&);
for(int i=;i<=tmp+&&i<K;i++)
dfs(x+,sta<<|i);
} int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
} int Get_Status() //用当前的并查集来求出新的点2到点k+1的最小表示
{
int sta=,tot=;
bool vis[Mx]; memset(vis,false,sizeof(vis));
for(int i=K+;i>=;i--)
if(!vis[i])
{
vis[i]=true,sta|=tot<<((i-)*);
for(int j=i-;j>=;j--)
if(find(i)==find(j))
vis[j]=true,sta|=tot<<((j-)*);
tot++;
}
return hash[sta];
} void cal(int sta,int addsta) //用加边状态addsta去更新最小表示法sta,addsta里的第i位为1表示第k+1个点要和点i+1连新边
{
for(int i=;i<=K+;i++) fa[i]=i;
for(int i=;i<=K;i++) //枚举点对(i,j)是否在最小表示法里的同一联通块内,将最小表示法中的连通性用并查集表示
for(int j=i+;j<=K;j++)
if((status[sta]>>((i-)*)&)==(status[sta]>>((j-)*)&))
{
int rooti=find(i),rootj=find(j);
if(rooti!=rootj) fa[rooti]=rootj;
}
for(int i=;i<=K;i++)
if(addsta&(<<(i-)))
{
int rooti=find(i),rootj=find(K+);
if(rooti==rootj) return; //判环,加的新边的两端点原来就是联通的,加入新边后会出现环
fa[rooti]=rootj;
}
bool flag=false; //flag=true表示有点和点1联通
for(int i=;i<=K+;i++)
if(find(i)==find())
{
flag=true; break;
}
if(!flag) return; //点1不链接后面的点,那么这个生成树不联通
trans.num[sta][Get_Status()]++;
} int main()
{
scanf("%d%lld",&K,&n);
dfs(,); A.n=; A.m=trans.n=trans.m=tot;
for(int i=;i<=tot;i++)
for(int j=;j<(<<K);j++) cal(i,j);
Pow(n-K); printf("%lld\n",A.num[][]);
return ;
}

bzoj1494【Noi2007】生成树计数的更多相关文章

  1. BZOJ1494 [NOI2007]生成树计数

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

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

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

  3. [NOI2007]生成树计数环形版

    NOI2007这道题人类进化更完全之后出现了新的做法 毕姥爷题解: 于是毕姥爷出了一道环形版的这题(test0814),让我们写这个做法 环形的情况下,k=5的时候是162阶递推. 求这个递推可以用B ...

  4. NOI2007 生成树计数

    题目 首先我要吐槽,这题目就是坑,给那么多无用的信息,我还以为要根据提示才能做出来呢! 算法1 暴力,傻傻地跟着提示,纯暴力\(40\)分,高斯消元\(60\)分. 算法2 DP!一个显然的东西是,这 ...

  5. [BZOJ1494]生成树计数

    [BZOJ1494] [NOI2007]生成树计数 Description 最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现:·n个结点的环的生成树个数为n.·n个结点的完全图的生成树 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Spring Cloud 入门 Eureka-Client服务提供

    前面文章介绍了如果创建“服务注册中心”,现在创建“服务提供者”,并向服务注册中心注册自己,在服务提供方中尝试着提供一个接口来获取当前所有的服务信息. 先,创建一个基本的Spring Boot应用.命名 ...

  2. django+xadmin在线教育平台(十)

    剩余app model注册 courses注册 新建courses/adminx.py: # encoding: utf-8 __author__ = 'mtianyan' __date__ = '2 ...

  3. datatable行内内容太长,有时不自动换行解决方法

    加一个css属性即可 style = "word-wrap:break-word;" js代码: "render": function (data, type, ...

  4. 7-4 python 接口开发(提供mock服务)

    1.登录接口开发(数据存在数据库中)  接口开发做mock(模拟功能) tools.py import pymysql def my_db(sql): conn = pymysql.connect(h ...

  5. 记一次samba排错 Failed to start Samba SMB Daemon.

       记录一次服务出错排错的过程,很多新手出了点错不百度直接巴拉巴拉的问,一般老手根据经验可以给出一点建议,但是由于个体环境的差异并不适用,反而埋怨起来.这种真的无F**K可说,所以要培养自己的排错能 ...

  6. 使用Docker 一键部署 LNMP+Redis 环境

    使用Docker 部署 LNMP+Redis 环境 Docker 简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linu ...

  7. javascript遍历方法总结

    forEach 循环 JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组的方法是这样的: for (var index = 0; index < myArray.lengt ...

  8. scrapy--boss直聘

    Hi,大家好.有段时间没来更新scrapy爬取实例信息了,前2天同事说爬取拉勾,boss直聘等网站信息比较困难.昨天下午开始着手爬取boss直聘内Python爬虫的信息,比想象中的简单很多. 需要解决 ...

  9. PLC状态机编程第五篇-状态机自动生成PLC程序

    这篇比较简单了,我就直接上图了,不多废话. 一.选择求解器,一定要选择定步长的. 二.右击Chart状态机,出现图上菜单 三.左边红色的勾选择,选择右侧的菜单,然后点击Generate Code按钮, ...

  10. perl语言入门总结-第2章

    $what ='steak'; print "fred ate $n ${what}s.\n"; 布尔值 如果是数字0为假, 如果是空字符串''为假, 如果即不是数字也不是字符串, ...