bzoj 1875

把边当做一个状态(orz居然有这种想法),初始点也看成边,然后矩阵快速幂就可以了(感觉有点像flyod)

 1 #include<bits/stdc++.h>
 2 #define inc(i,l,r) for(int i=l;i<=r;i++)
 3 #define dec(i,l,r) for(int i=l;i>=r;i--)
 4 #define link(x) for(edge *j=h[x];j;j=j->next)
 5 #define mem(a) memset(a,0,sizeof(a))
 6 #define inf 45989
 7 #define ll long long
 8 #define succ(x) (1<<x)
 9 #define NM 300
10 using namespace std;
11 int read(){
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
14     while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
15     return x*f;
16 }
17 struct mat{
18     int a[NM][NM];
19 }c,_t;
20 int n,m,S,T,a[NM],b[NM],ans;
21 mat operator*(const mat&x,const mat&y){
22     mat s;mem(s.a);
23     inc(i,1,m)
24     inc(j,1,m)
25     inc(k,1,m)
26     (s.a[i][j]+=x.a[i][k]*y.a[k][j]%inf)%=inf;
27     return s;
28 }
29 ll k;
30 int main(){
31     freopen("data.in","r",stdin);
32     n=read();m=read();k=read();S=read()+1;T=read()+1;
33     inc(i,1,m){
34         a[i*2-1]=b[i*2]=read()+1;b[i*2-1]=a[i*2]=read()+1;
35     }
36     m<<=1;
37     inc(i,1,m)c.a[i][i]=1;
38     inc(i,1,m)
39     inc(j,1,m)
40     if((i-1)/2!=(j-1)/2&&b[i]==a[j])_t.a[i][j]=1;
41     /*inc(i,1,m){
42     inc(j,1,m)printf("%d ",_t.a[i][j]);printf("\n");}*/
43     for(k--;k;k>>=1,_t=_t*_t)
44     if(k&1)c=c*_t;
45 /*    inc(i,1,m){
46     inc(j,1,m)printf("%d ",c.a[i][j]);printf("\n");}*/
47     inc(i,1,m)if(a[i]==S)
48     inc(j,1,m)if(b[j]==T)
49     (ans+=c.a[i][j]%inf)%=inf;
50     printf("%d\n",ans);
51     return 0;
52 }

时间: 2025-01-01 03:03:33

bzoj 1875的相关文章

[BZOJ 1875] [SDOI 2009] HH去散步【矩阵乘法】

题目链接:BZOJ - 1875 题目分析: 这道题如果去掉“不会立刻沿着刚刚走来的路走回”的限制,直接用邻接矩阵跑矩阵乘法就可以了.然而现在加了这个限制,建图的方式就要做一些改变.如果我们把每一条边看做点建矩阵,那么每次从一条边出发都只会到其他的边,不能仍然在这条边上“停留”,所以这就可以满足题目的限制.将每条边拆成两条单向边,比如一条编号为 4,一条编号为 5.那么 4^1=5, 5^1=4.这样只要不从第 i 条边走到 i 或 i^1 就可以了.初始的矩阵中以 A 为起点的边到达的方案数为

bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法

1875: [SDOI2009]HH去散步 Time Limit: 20 Sec  Memory Limit: 64 MB Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢变化的人,所以他每 天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法. 现在给你学校的地图(假设每条路的长度都 是一样的都是1),问长度为t,从给定

BZOJ 1875[SDOI2009]HH去散步

题面: 1875: [SDOI2009]HH去散步 Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1750  Solved: 851[Submit][Status][Discuss] Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢变化的人,所以他每 天走过的路径都不完全一样,他想知

BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )

把双向边拆成2条单向边, 用边来转移...然后矩阵乘法+快速幂优化 --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MOD = 45989; const int

【BZOJ 1875】【SDOI 2009】HH去散步

水啊水,最后ans别忘了%哦! #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int mo = 45989; int cnt = 1, point[23], n, m, t, S, T; struct node { int u, v, nxt; } E[1003]; struct Mt { int v[123][123]; Mt() {memset(v,

bzoj 1875 [SDOI2009]HH去散步(矩乘)

Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法. 现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径 Input 第一行:五个整数N,M,t,A,B.其中N表示学校里的路口的个数,M表

BZOJ 1875 SDOI 2009 HH去散步 矩阵乘法优化DP

题目大意:给出一张无向图,求从A到B走k步(不能走回头路)的方案数.(k <= 2^30) 思路:看到k的范围就知道是矩阵乘法了.关键是不能走回头路怎么构造.正常的方法构造点的转移不能避免这个问题,就用边来构造.只要保证不经过自己^1的边就可以保证不走回头路了. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX

[DP 矩阵快速幂] BZOJ 1875 [SDOI2009]HH去散步

一个DP 用矩阵快速幂加速 然后这个DP状态比较巧妙 以边作状态 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define cl(x) memset(x,0,sizeof(x)) using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==

BZOJ1875 HH去散步

这题 我承认 我过于NAIVE了 我把不能走回边 搞成了 走到一个点必须休息一下... 发现它的边数非常少 所以 按边建立矩阵 就可以十分科学的完成本题 矩乘我一定要封装进p,q BZOJ 1875 1 #include<bits/stdc++.h> 2 #define mod 45989 3 #define ll long long 4 #define breaks printf("!\n"); 5 using namespace std; 6 7 inline int