bzoj1494
这道题不仅得看俞华程的论文,还得看陈丹琦的论文,否则是不可能做出来的。因为难点在构造矩阵上。
构造矩阵困难在如何表示状态,因为树不能有环,也不能不连通,这里我们引入了最小表示法来表示连续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的更多相关文章
- 【BZOJ1494】【NOI2007】生成树计数(动态规划,矩阵快速幂)
[BZOJ1494][NOI2007]生成树计数(动态规划,矩阵快速幂) 题面 Description 最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现: ·n个结点的环的生成树个数为 ...
- [BZOJ1494]生成树计数
[BZOJ1494] [NOI2007]生成树计数 Description 最近,小栋在无向连通图的生成树个数计算方面有了惊人的进展,他发现:·n个结点的环的生成树个数为n.·n个结点的完全图的生成树 ...
- bzoj1494 生成树计数 (dp+矩阵快速幂)
题面欺诈系列... 因为一个点最多只能连到前k个点,所以只有当前的连续k个点的连通情况是对接下来的求解有用的 那么就可以计算k个点的所有连通情况,dfs以下发现k=5的时候有52种. 我们把它们用类似 ...
- BZOJ1494 [NOI2007]生成树计数
题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser autoint Logout 捐赠本站 Probl ...
- [BZOJ1494][NOI2007]生成树计数 状压dp 并查集
1494: [NOI2007]生成树计数 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 793 Solved: 451[Submit][Status][ ...
- bzoj1494【Noi2007】生成树计数
题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1494 sol :前排膜拜http://blog.csdn.net/qpswwww/artic ...
- 插头dp初探
问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
随机推荐
- JPQL 的基本使用
一.概念 JPQL 语言,即 Java Persistence Query Language 的简称.JPQL 和 HQL 是非常类似的,支持以面向对象的方式来写 SQL 语句,当然也支持本地的 SQ ...
- php第二十九节课
文件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...
- Luogu P4549 裴蜀定理 / Min
思路 题目已经给出了正解.我们只需要将裴蜀定理推广到若干数的线性组合就可以做这道题了 要注意的是需要在输入的时候取一个绝对值.因为可能会有负数存在.我之前也写过裴蜀定理的证明,要看的话点这里 吐槽 第 ...
- Error:Cannot find bean: "org.apache.struts.taglib.html.BEAN" in any scope
原因:html标签和struts标签混用,或者表单元素外面没有<html:form>标签包裹. 解决:统一标签 <html:form action="/login.do&q ...
- 07.C语言:结构体、共用体、枚举
一.结构体 是一种复合的数据类型,由多个不同类型的数据(为结构体的成员)组成的集合. 在c语言中没有给出结构体这种类型具体的形式(名称),但是给出类定义该结构体类型的方法(格式). 在使用结构体类型时 ...
- PAT 1122 Hamiltonian Cycle
The "Hamilton cycle problem" is to find a simple cycle that contains every vertex in a gra ...
- 【Codeforces 1096D】Easy Problem
[链接] 我是链接,点我呀:) [题意] 让你将一个字符串删掉一些字符. 使得字符串中不包含子序列"hard" 删掉每个字符的代价已知为ai 让你求出代价最小的方法. [题解] 设 ...
- 线段树题集 (cf版)
lazy区间修改 : http://acm.hdu.edu.cn/showproblem.php?pid=4902 (hdu4902) http://acm.hdu.edu.cn/showpr ...
- Codeforces 314B(倍增)
题意:[a,b]表示将字符串a循环写b遍,[c,d]表示把字符串c循环写d遍,给定a,b,c,d,求一个最大的p,使得[[c,d],p]是[a,b]的子序列(注意不是子串,也就是不要求连续).(b,d ...
- 眼镜h5
// 填充博乐纯门店数据 (function() { var $biotrueCitySelect = $('.regional-popup select.city'); jQuery.each(st ...