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 ...
随机推荐
- adb 命令收藏学习地址
adb 命令相关的网页https://www.cnblogs.com/medsonk/p/8334847.htmlhttps://www.cnblogs.com/medsonk/p/6959658.h ...
- P1091 合唱队形题解(洛谷,动态规划LIS,单调队列)
先上题目 P1091 合唱队形(点击打开题目) 题目解读: 1.由T1<...<Ti和Ti>Ti+1>…>TK可以看出这题涉及最长上升子序列和最长下降子序列 2 ...
- Struts2学习笔记:DMI,多个配置文件,默认Action,后缀
动态方法调用有三种方法: 1.同一Action多次映射,每个action标签的method对应要调用的方法. 当要调用的方法多了就会增加struts.xml文件的复杂性. 2.struts.Dynam ...
- 洛谷 4302 BZOJ 1090 SCOI2003 字符串折叠 UVA1630 Folding(输出方案版)
[题解] 区间DP. 设f[i][j]表示i~j的最小代价.再枚举中间点k,很容易想到转移方程为f[i][j]=min(f[i][j],f[i][k]+f[k][j]),同时如果i~k可以通过重复获 ...
- MaxScale初探
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://mrcto.blog.51cto.com/1923168/1437287 内容预览 ...
- 转载 - Struts2拦截器配置
出处:http://blog.csdn.net/axin66ok/article/details/7321430 目录(?)[-] 理解拦截器 1 什么是拦截器 2 拦截器的实现原理 拦截器的配置 使 ...
- [codeVS1404] 字符串匹配
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度. ...
- $scope的生命周期
model mutation 模型改变 model observation 模型观察 scope destruction scope结束 神奇的scope,一个angular应用只有一个scope,一 ...
- ECMAScript 6 入门学习笔记(零)——开始
所有es6笔记都是我自己提出来的一些点,没有很详细的例子什么的,这个链接就是我看的教程,有需要的可以看看.(http://es6.ruanyifeng.com/#docs/intro) 1.ECMAS ...
- 洛谷—— P2504 [HAOI2006]聪明的猴子
P2504 [HAOI2006]聪明的猴子 题目描述 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个雨林的地表还是被大水淹没着,部分植物的树冠露在水面上. ...