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 ...
随机推荐
- 汇编学习pushl, popl
- myeclipse工具常用的用法
1. 自动提示:窗口->首选项->Java->编辑器->内容辅助->自动激活,在下面的“Java的自动激活触发器里面填上“.abcdefghijklmnopqrstuv ...
- C++ CEF 浏览器中显示 Tooltip(标签中的 title 属性)
在 Windows 中将 CEF 集成到 C++ 客户端以后,默认是无法显示 tooltip 的,比如图片标签中的 title 属性. 实现的方式其实很简单,按下面的步骤操作就可以: 创建一个文本文件 ...
- 腾讯云:iptables基础
iptables 基础 iptables 基本命令 任务时间:5min ~ 10min iptables 可以简单理解为 Linux 系统内核级防火墙 netfilter 的用户态客户端. Linux ...
- 电商架构设计-通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性
个人观察 1.通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性. 2.单一职责原则SRP,真的很关键,广大程序员需要不断深入理解这个原则. 3.架构图是架构师的重要输出,通过图 ...
- Entity SQL rules for Wrapped and Unwrapped Results
Here are some rules to remember for Entity SQL queries: 1.Use SELECT VALUE when projecting more than ...
- [K/3Cloud]调用动态表单时,传递自定义参数
插件中在调用动态表单时,通过DynamicFormShowParameter的CustomParams,增加自定义的参数. private void ShowMaterialStock() { obj ...
- CentOS 安装Oracle 11g R2
CentOS 安装Oracle 11g R2 学习了-/ https://www.osyunwei.com/archives/5445.html
- 初识iBatis
在JAVA EE应用程序中,持久层框架常用的有:Hibernate和IBATIS(或MyBatis),Hibernate是全自动的,IBatis是半自动的. IBatis的主要的作用是把SQL语句从我 ...
- Ubuntu 16.04安装Adobe AIR
安装: wget -O adobe-air.sh http://drive.noobslab.com/data/apps/AdobeAir/adobe-air.sh chmod +x adobe-ai ...