【47.40%】【BZOJ 1875】[SDOI2009]HH去散步
Time Limit: 20 Sec Memory Limit: 64 MB
Submit: 1363 Solved: 646
[Submit][Status][Discuss]
Description
HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。 现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径
Input
第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。 接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai = Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。
答案模45989。
Output
一行,表示答案。
Sample Input
0 1
0 2
0 3
2 1
3 2
Sample Output
HINT
对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。 对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B
【题解】
类似的题目。
给出n*n的邻接矩阵。1表示从某个节点到某个节点有一条有向边。
求从任意一个节点到任意一个节点恰好走k步到达的方案数。
如果是这样的问题。直接把邻接矩阵看成是一个矩阵A,然后求A^k即可。
这一题如果不加上那个不走重路的条件则和这个例子是一样的。
但是加了之后就不能单纯地用这种方法来做了。
需要换一个思路。就是把所有的边看成是一个点。
然后矩阵A[i][j]记录的是第i条边是否链接着第j条边。如果链接着则为1否则为0;
因为我们用邻接表来存储给出的边。所以很容易求出哪两条边(a,b)满足
a->终点==b->起点。且要求b的终点不为a(我们一开始会把无向图处理成两条有向图,所以会有反边)
而我们处理边的时候同时add(x,y)且add(y,x);
所以这两条边的编号一个为奇数一个为偶数。
且它们的编号是相邻的。
我们在判断两条这样符合要求的边(a,b)的时候。就可以根据奇偶性来判断它们是不是一对相反的边。
先不考虑把边化为点。
有这样一个图
a->b->c;
假设a->b这条边的编号为1.b->c这条边的编号为3;
则我们在边化点的时候
a[1][3]=1;
而我们如果要求k=2;
则只需要把化成的矩阵A做A^(k-1)即可(而A^1就是A本身);
然后化一个虚拟的节点t0.
这个t0指向起点a的所有出度边。
for (int i = first[a];i;i= next[i])
B.v[1][i] = 1;
然后把矩阵B和做过乘方的矩阵A相乘(一定是矩阵B和矩阵A相乘,矩阵乘法没有交换律);
得到新的矩阵A;
A[1][1..totm]就是起点指向所有边的方案数(从起点到那条边的终点的方案数);
∑A[1][终点的出度边的相反边] % MOD即为答案;
【代码】
#include <cstdio>
#include <cstdlib> const int MAX_M = 60;
const int MAX_N = 21;
const int MOD = 45989; int n, m, t, a, b,totm = 0,final_ans = 0;
int next[MAX_M * 3], en[MAX_M * 3],first[MAX_N]; struct juzhen
{
int v[MAX_M * 3][MAX_M * 3];
}; juzhen X, Y,ans,c,temp; void add(int x, int y)
{
totm++;
next[totm] = first[x];
first[x] = totm;
en[totm] = y;
} void input_data()
{
scanf("%d%d%d%d%d", &n, &m, &t, &a, &b);
a++; b++;
for (int i = 1; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
x++; y++;
add(x, y);
add(y, x);
}
} int fan(int x)
{
if (x & 1)
return x + 1;
return x - 1;
} juzhen cheng(juzhen a, juzhen b)
{ return c;
} void chengfang(int now)//矩阵快速幂;
{
if (now <= 1)
return;
chengfang(now >> 1);
for (int i = 1; i <= totm; i++)
{
for (int what = 1; what <= totm; what++)
{
c.v[i][what] = 0;
for (int j = 1; j <= totm; j++)
c.v[i][what] = (c.v[i][what] + Y.v[i][j] * Y.v[j][what]) % MOD;
}
}
for (int i = 1; i <= totm; i++)
for (int j = 1; j <= totm; j++)
Y.v[i][j] = c.v[i][j];
if (now & 1)
{
for (int i = 1; i <= totm; i++)
{
for (int what = 1; what <= totm; what++)
{
c.v[i][what] = 0;
for (int j = 1; j <= totm; j++)
c.v[i][what] = (c.v[i][what] + Y.v[i][j] * temp.v[j][what]) % MOD;
}
}
for (int i = 1; i <= totm; i++)
for (int j = 1; j <= totm; j++)
Y.v[i][j] = c.v[i][j];
}
} void get_ans()
{
for (int i = first[a]; i; i = next[i])
X.v[1][i] = 1;
for (int i = 1; i <= totm; i++)
for (int j = first[en[i]]; j; j = next[j])
if (j != fan(i))
{
Y.v[i][j] = 1;
temp.v[i][j] = 1;
}
chengfang(t - 1);//A^(t-1);
for (int i = 1; i <= totm; i++)//把那个系数矩阵和做过乘方的矩阵相乘(注意顺序);
{
for (int what = 1; what <= totm; what++)
{
c.v[i][what] = 0;
for (int j = 1; j <= totm; j++)
c.v[i][what] = (c.v[i][what] + X.v[i][j] * Y.v[j][what]) % MOD;
}
}
for (int i = 1; i <= totm; i++)
for (int j = 1; j <= totm; j++)
ans.v[i][j] = c.v[i][j];
for (int i = first[b]; i; i = next[i])
final_ans = (final_ans + ans.v[1][fan(i)]) % MOD;
} void special_judge()
{
if (t == 0)
{
if (a == b)
printf("1\n");
else
printf("0\n");
exit(0);
}
} void output_ans()
{
printf("%d\n", final_ans);
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
// freopen("F:\\rush_out.txt", "w", stdout);
input_data();
special_judge();
get_ans();
output_ans();
return 0;
}
【47.40%】【BZOJ 1875】[SDOI2009]HH去散步的更多相关文章
- BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )
把双向边拆成2条单向边, 用边来转移...然后矩阵乘法+快速幂优化 ------------------------------------------------------------------ ...
- bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法
1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走, ...
- bzoj 1875 [SDOI2009]HH去散步(矩乘)
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因 ...
- bzoj 1875: [SDOI2009]HH去散步
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...
- BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)
首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...
- BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)
题目链接 比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边 如果这样表示是不好转移的 可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 ...
- BZOJ 1875 [SDOI2009]HH去散步 ——动态规划 矩阵乘法
发现t非常大,所以大概就是快速幂一类的问题了, 然后根据k^3logn算了算,发现k大约是边数的时候复杂度比较合适. 发现比较麻烦的就是前驱的记录,所以直接把边看做点,不能走反向边,但是可以走重边,然 ...
- 【BZOJ】1875: [SDOI2009]HH去散步
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1875 注意的是路径不可以重复,所以这题把边看成点.每一条无向边拆成两条有向边. 令${F[ ...
- 【BZOJ】1875: [SDOI2009]HH去散步 矩阵快速幂
[题意]给定n个点m边的无向图,求A到B恰好经过t条边的路径数,路径须满足每条边都和前一条边不同.n<=20,m<=60,t<=2^30. [算法]矩阵快速幂 [题解]将图的邻接矩阵 ...
- 1875. [SDOI2009]HH去散步【矩阵乘法】
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...
随机推荐
- day4_python-之装饰器、迭代器、生成器
一.装饰器 1.为何要用装饰器 #开放封闭原则:对修改封闭,对扩展开放 2. 什么是装饰器 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象. 强调装饰器的原则:1 不修改被 ...
- Cmakelists.txt中配置glfw
qt中需要用cmake编译工程,且需要用到OpenGL库glfw,如何给Cmakelist.txt配置glfw的动态链接库? 在Cmakelists.txt添: find_package(glfw3 ...
- 【New Feature】阿里云快照服务技术解析
一.背景 目前上云已经成为行业发展趋势,越来越多的企业级客户将业务系统和数据库迁移到云上.而传统的备份一体机/备份软件方式,并不适合云上ECS.RDS等产品的备份与容灾服务.阿里云块存储服务提供云 ...
- ArcGIS 发布高程服务。10.4
ArcGIS 发布高程必须是10.21以上,我用10.4. 前端用ArcGIS For API 4.x. ARCGIS很早之前有CS版本的ArcScene,可查看高程TIF文件,但机制和BS的完全不同 ...
- SQL Server —— 主键和外键
一.定义 1.1.什么是主键和外键 关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键. 比如: 学生表(学号,姓名,性别,班级)其中 ...
- HLSL像素着色器
原文:HLSL像素着色器 昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 手机淘宝二维码 扫描 或者打开连接:程序设计开发 ,掌声鼓励,欢迎光临. 像素着色器替代了固定渲染管线的 ...
- WPF 线段Line过长渲染出现的问题
原文:WPF 线段Line过长渲染出现的问题 在使用WPF的时候,可以做一个实验,在canvas里添加一条线段Line,StrokeThickness属性设置为1,然后通过放大canvas或者调整li ...
- iOS iOS8注册通知
http://blog.csdn.net/apple_app/article/details/39228221 极光推送 action设置 http://docs.jpush.cn/display/d ...
- 阿里云亮相2019联通合作伙伴大会,边缘计算等3款云产品助力5G时代产业数字化转型
4月23日,2019中国联通合作伙伴大会在上海正式开幕,本次大会以“合作不设限,共筑新生态”为主题,涉及5G.边缘计算.云计算.物联网.新媒体.人工智能.互联网化等各领域超过600家合作伙伴与3万名各 ...
- java future模式 所线程实现异步调用(转载
java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...