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

这道题。。因为k很小,而且我们只关心连续的k个节点的连通性,所以把连续的k个点轮廓线上的连通性的最小表示当做状态来转移。

转移可以构造一个矩阵,构造矩阵不难想,但挺麻烦的。。。

时间复杂度\(O(Mlen2^kk^2+Mlen^3logn)\),Mlen最坏情况下为52。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ui p = 65521; ui ipow(ui a, ui b) {
ui t = 1, w = a;
while (b) {
if (b & 1) t = (t * w) % p;
w = (w * w) % p;
b >>= 1;
}
return t;
} int k;
ll n; struct data {
int a[5];
} state[53]; int cnt[5], tot = 0, max_now, bi[5], ref[1000003];
ui f[53], ret, rr; void checkmin(int num) {
rr = num;
for (int i = 0; i < k; ++i) {
bi[i] = num % 10;
if (bi[i] >= k) return;
num /= 10;
} max_now = -1;
for (int i = 0; i < k; ++i)
if (bi[i] > max_now + 1) return;
else max_now = max(max_now, bi[i]); ++tot; memset(cnt, 0, sizeof(cnt)); ref[rr] = tot;
for (int i = 0; i < k; ++i)
state[tot].a[i] = bi[i], ++cnt[bi[i]];
ret = 1;
for (int i = 0; i < k; ++i)
if (cnt[i] > 1)
ret = ret * ipow(cnt[i], cnt[i] - 2) % p;
f[tot] = ret;
} struct Matrix {
ui a[53][53];
Matrix() {memset(a, 0, sizeof(a));}
} W, T; Matrix operator * (Matrix A, Matrix B) {
Matrix C;
for (int k = 1; k <= tot; ++k)
for (int i = 1; i <= tot; ++i)
for (int j = 1; j <= tot; ++j)
C.a[i][j] = (C.a[i][j] + (A.a[i][k] * B.a[k][j] % p)) % p;
return C;
} bool flag, vis[100003];
int col[5], ora[5]; void mark_matrix(int row, int *pre) {
flag = true; max_now = 0;
for (int i = 1; i < k; ++i) {
max_now = max(max_now, pre[i]);
if (pre[i] == pre[0])
flag = false;
} int totnum = (1 << (max_now + 1)), mark, lalala, now;
ret = 0;
for (int i = 0; i < totnum; ++i) {
if (flag && (i & 1) == 0) continue;
mark = -1;
for (int j = 0; j < k; ++j) col[j] = j;
for (int j = 0; j <= max_now; ++j)
if ((1 << j) & i) {
if (mark == -1) mark = j;
else col[j] = mark;
} memset(ora, -1, sizeof(ora)); lalala = -1;
for (int j = 1; j < k; ++j)
if (ora[col[pre[j]]] == -1) bi[j - 1] = (ora[col[pre[j]]] = ++lalala);
else bi[j - 1] = ora[col[pre[j]]]; if (mark != -1 && ora[mark] != -1) bi[k - 1] = ora[mark];
else bi[k - 1] = ++lalala; now = bi[k - 1];
for (int j = k - 2; j >= 0; --j) now = now * 10 + bi[j];
if (!ref[now]) continue;
ret = 1;
if (mark != -1)
for (int j = 0; j < k; ++j)
if (col[j] == mark) {
rr = 0;
for (int l = 0; l < k; ++l)
if (pre[l] == j) ++rr;
ret = ret * rr % p;
} W.a[row][ref[now]] = ret;
}
} int main() {
scanf("%d%lld", &k, &n); if (k >= n) {printf("%u\n", ipow(n, n - 2)); return 0;} int bas = 1; for (int i = 1; i <= k; ++i) bas = bas * 10;
for (int i = 0; i <= 43210; ++i)
if (!vis[i % bas])
checkmin(i), vis[i % bas] = true; n -= k;
for (int i = 1; i <= tot; ++i)
mark_matrix(i, state[i].a); /* for (int i = 1; i <= tot; ++i) {
for (int j = 1; j <= tot; ++j)
printf("%d ", W.a[i][j]);
puts("");
}*/ for (int i = 1; i <= tot; ++i)
T.a[i][i] = 1; while (n) {
if (n & 1) T = W * T;
W = W * W;
n >>= 1;
} /* puts("");
for (int i = 1; i <= tot; ++i) {
for (int j = 1; j <= tot; ++j)
printf("%d ", T.a[i][j]);
puts("");
}*/ ui ans = 0;
for (int i = 1; i <= tot; ++i)
ans = (ans + f[i] * T.a[i][1] % p) % p;
printf("%u\n", ans); return 0;
}

【BZOJ 1494】【NOI 2007】生成树计数的更多相关文章

  1. 线性代数(矩阵乘法):NOI 2007 生成树计数

    这道题就是深搜矩阵,再快速幂. #include <iostream> #include <cstring> #include <cstdio> #include ...

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

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

  3. BZOJ1494 [NOI2007]生成树计数

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

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

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

  5. [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会

    [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会 题意 给定一个长度为 \(n\) 的字符串 \(s\), 对于所有 \(r\in[1,n]\) 求出 \(s\ ...

  6. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

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

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

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

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

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

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

  10. 「UVA10766」Organising the Organisation(生成树计数)

    BUPT 2017 Summer Training (for 16) #6C 题意 n个点,完全图减去m条边,求生成树个数. 题解 注意可能会给重边. 然后就是生成树计数了. 代码 #include ...

随机推荐

  1. StackExchange.Redis客户端读写主从配置,以及哨兵配置。

    今天简单分享一下StackExchange.Redis客户端中配置主从分离以及哨兵的配置. 关于哨兵如果有不了解的朋友,可以看我之前的一篇分享,当然主从复制文章也可以找到.http://www.cnb ...

  2. Java之继承、抽象类、接口篇

    一.继承(extends) 什么是继承? 继承是对现实生活中的"分类"概念的一种模拟. 狮子拥有动物的一切基本特性,但同时又拥有自己的独特的特性,这就是"继承" ...

  3. Java的Debug调试

    一.在项目上右键,Debug As>Debug on Server 二.在测试类上,Run As>Run On Server

  4. ArcGIS Engine开发前基础知识(4)

    ArcGIS不同开发方式的比较 关于GIS应用软件的开发,通常有三种方式:C/S架构.网络GIS和移动GIS.ArcGIS平台提供了对三种开发方式的支持,对于采用从C/S架构的大多数开发者来讲,首先想 ...

  5. 架构从最简单的数据访问框架(ORM)到资源调度和治理中心(SOA)说起

    随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构当网站流量很小时,只需一个应用,将 ...

  6. linux Mysql 安装及配置

    1.准备 cmake-3.6.0.tar.gz bison-3.0.4.tar.gz mysql-5.7.13.tar.gz (http://dev.mysql.com/get/Downloads/M ...

  7. git-入门

    一.简介 Git是目前世界上最先进的分布式版本控制系统,Git中绝大部分操作都是访问本地资源,不需要网络,其中有三个概念比较重要:1. 工作目录 2. 暂存区域 3.本地仓库. 简单说明一下,工作目录 ...

  8. SQL基础教程--实现增删查改功能(W3School)

    1.SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL). SQL (结构化查询语言)是用于执行查询的语法.但是 SQL 语言也包含用于更新 ...

  9. SQL Server查询第31到40条数据

    大致分为两种情况:ID连续和ID不连续. 1.ID连续的情况: 2.ID不连续的情况: (1).两次对表查询,效率较低. ID from A) (2).外层查询没有对表A进行查询,效率提高. ID f ...

  10. Scala访问修饰符(四)

    Scala 访问修饰符基本和Java的一样,分别有:private,protected,public. 如果没有指定访问修饰符符,默认情况下,Scala对象的访问级别都是 public. Scala ...