这道题不仅得看俞华程的论文,还得看陈丹琦的论文,否则是不可能做出来的。因为难点在构造矩阵上。

构造矩阵困难在如何表示状态,因为树不能有环,也不能不连通,这里我们引入了最小表示法来表示连续k个点的连通性。

首先我们找出所有可能的状态,dfs一下就行了,最多只有53种。然后计算每种状态的形态,状态只是表示了连通性,但没有表示之间的形态。于是我们初始每种状态形态的数量作为列向量。然后就是构造转移矩阵。这个转移矩阵表示一个状态能够转移到另一个状态,其实是每次向前移动一位。每次向前移动一位也就是说对于一个状态我们要找出所有可以成为这个状态后移一位的合法的状态。每两个状态之间系数矩阵上的值为可能的形态数,这里的形态数和刚才不太一样,向后移一位说明把当前k个点去掉了第一个点,然后又添加了一个点。这里我们用二进制枚举连通性,也就是说新加入的点和之前k个点中哪些点是联通的。那么这样的连通性会有很多情况,比如说原来的最小表示是001,二进制枚举出来的是11,那么新的点既要和第一个联通块联通,也要和第二个联通块联通,也就是有两种情况,即是(设这个点为4,之前为123)(4->1, 4->3) (4->2,4->3)两种联通情况。

最后统计答案是这样做的,因为最后只有一种合法状态,即0....0,必须所有都联通,所以sigma(f[i][1]*ret[i][1]),i->1表示所有能转移到1状态的情况。

然后就可以矩阵快速幂了。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = , M = , mod = ;
struct mat {
ll a[N][N];
} A, f;
ll k, n;
int mir[N], cnt[N], p[N], bit[], vis[N];
ll power(ll x, ll t)
{
ll ret = ;
for(; t; t >>= , x = x * x % mod) if(t & ) ret = ret * x % mod;
return ret;
}
void collect(int x)
{
int cnt[]; memset(cnt, , sizeof(cnt)); f.a[p[]][] = ; mir[x] = p[];
for(int i = ; i <= k; ++i) ++cnt[x % ], x /= ;
for(int i = ; i < k; ++i) if(cnt[i] > ) f.a[p[]][] = f.a[p[]][] * power(cnt[i], cnt[i] - ) % mod;
}
void dfs(int num, int d, int bound, int x)
{
if(d == k) { p[++p[]] = num; collect(p[p[]]); return; }
for(int i = ; i <= bound; ++i) dfs(num + i * x, d + , max(i + , bound), x / );
}
void Init(int pos)
{
memset(bit, , sizeof(bit));
int x = p[pos], maxn = -; bool flag = true;
for(int j = , l = x; j < k; ++j) bit[k - j - ] = l % , l /= ;
for(int i = ; i < k; ++i)
{
if(bit[i] == bit[]) flag = false;
maxn = max(maxn, bit[i]);
}
int lim = << (maxn + );
for(int i = ; i < lim; ++i)
{ //枚举连通性, 枚举和原来的每位是否联通
if(flag && !(i & )) continue; //不成立的情况
for(int j = , l = x; j < k; ++j) bit[k - j - ] = l % , l /= ;
bit[k] = -;
int ans = , l = -, tot = ; ;
for(int j = ; j <= maxn; ++j) if(i & ( << j))
{
int t = ;
for(int x = ; x < k; ++x) if(bit[x] == j) bit[x] = -, ++t;
ans = ans * t;
}
memset(vis, , sizeof(vis));
for(int j = ; j <= k; ++j) if(!vis[j])
{
int color = bit[j]; bit[j] = ++l; vis[j] = ;
for(int x = ; x <= k; ++x) if(bit[x] == color && !vis[x])
bit[x] = l, vis[x] = ;
}
for(int j = ; j <= k; ++j) tot = tot * + bit[j];
A.a[pos][mir[tot]] = ans % mod;
}
}
mat operator * (mat A, mat B)
{
mat ret; memset(ret.a, , sizeof(ret.a));
for(int i = ; i <= p[]; ++i)
for(int j = ; j <= p[]; ++j)
for(int k = ; k <= p[]; ++k) ret.a[i][j] = (ret.a[i][j] + A.a[i][k] % mod * B.a[k][j] % mod) % mod;
return ret;
}
int main()
{
scanf("%d%lld", &k, &n);
if(k >= n) { printf("%lld\n", power(n, n - )); return ; }
int base = ; for(int i = ; i < k; ++i) base = base * ;
dfs(, , , base);
for(int i = ; i <= p[]; ++i) Init(i);
mat ret; memset(ret.a, , sizeof(ret.a)); for(int i = ; i <= p[]; ++i) ret.a[i][i] = ;
for(ll t = n - k; t; t >>= , A = A * A) if(t & ) ret = ret * A;
ll ans = ;
for(int i = ; i <= p[]; ++i) ans = (ans + f.a[i][] * ret.a[i][]) % mod;
printf("%lld\n", ans);
return ;
}

bzoj1494的更多相关文章

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

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

  2. [BZOJ1494]生成树计数

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

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

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

  4. BZOJ1494 [NOI2007]生成树计数

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

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

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

  6. bzoj1494【Noi2007】生成树计数

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1494 sol  :前排膜拜http://blog.csdn.net/qpswwww/artic ...

  7. 插头dp初探

    问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...

  8. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

随机推荐

  1. 数据导出为Excel(未完)

    更多详细内容 view页面: function Download() { //多个查询条件 dateStart = $("#j_dataTimeStart").datebox(&q ...

  2. TWaver 3D应用于大型数据中心(续)

    在2014年11月份,我们当时发了一篇有关TWaver HTML5 3D应用于大型数据中心的文章,该blog比较详细的描述一些常用的功能的实现方法,比如:动态添加机柜,告警,温度,湿度等相关的功能的具 ...

  3. How To:分析ORACLE监听日志中的IP信息

    有时候需要分析出ORACLE日志监听中的IP信息,分享一个组合命令,Linux的shell下运行正常. grep "HOST=.*establish.*\* 0" listener ...

  4. js识别手机访问自动跳转到相应页面

    /* * 智能机浏览器版本信息: * */ var browser={ versions:function(){ var u = navigator.userAgent, app = navigato ...

  5. Python面向对象之私有属性和方法

    私有属性与私有方法 应用场景 在实际开发中,对象的某些属性或者方法 可能只希望在对象的内部被使用,而不希望在外部被访问到: 私有属性 就是对象不希望公开的属性: 私有方法 就是对象不希望公开的方法: ...

  6. Packages on Ubuntu OS

    openSSH https://help.ubuntu.com/lts/serverguide/openssh-server.html

  7. SQL学习笔记:库和表的创建

    目录 创建和删除数据库 创建和删除表 添加.修改和删除字段 创建和删除数据库 CREATE DATABASE justForLearn; DROP DATABASE justForLearn; 创建和 ...

  8. nyoj 31 5个数求最值

    5个数求最值 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 设计一个从5个整数中取最小数和最大数的程序   输入 输入只有一组测试数据,为五个不大于1万的正整数 输 ...

  9. [K/3Cloud]关于K/3 Cloud v2.0升级补丁的疑问

    现在除了K/3 Cloud v2.0的正式版之外,后续又发布了SP1和SP2补丁包.改善了一些问题和BUG,有些人之前可能之前装了SP1,有的可能没装过.在这里我说明一下: 不管装没装过补丁直接打SP ...

  10. 页面加载即执行JQuery的三种方法

    [1]$(function( ){ }): $(function(){ $("#name").click(function(){ //adding your code here } ...