截止目前最失败的一次比赛,奇耻大辱啊,orz……
卡在一些比较难写的题目里面,思路不清晰就在瞎敲代码,越改越死……
我们完全丢了一队的脸,甚至连二队三队都不如了,差点还进不了决赛,失眠难受了一整天……
事后还是那样,抛开这一切,许多问题变得明了起来,对于一些题目赛场上有猜测,后来发现也是对的,但因为陷入一道题而没去完善……
什么都不说了,WHU,雪耻之战!
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
As one of the most beautiful campus in China, Wuhan University is around several hills, so the road is complex and visitors always lose themselves. Give a undirected graph of WHU ofNNN points and a deadline, then you should count the number of plan to reach the destination by deadline (the starting point is 1 and the ending point isNNN).
First line contains the number of points NNN (N≤100N\le 100N≤100) and the number of edges MMM (M≤N(N−1)/2M\le N(N-1)/2M≤N(N−1)/2).
The iii-th line of next MMM lines contains two numbers uiu_iui and viv_ivi, which respents an edge (ui,vi)(u_i, v_i)(ui,vi).
The last line contains the deadline TTT(T≤109T\le 10^9T≤109).
The number of plan to reach the destination by deadline module 109+710^9+7109+7.
4 5
1 3
2 3
3 4
1 2
1 4
8
170
没错和在赛场的时候想的一样,用邻接矩阵+矩阵快速幂。根据邻接矩阵的性质,同一个矩阵自己进行矩阵乘法,在得到的矩阵x中x[i][j]的数值表示从i出发经过一个中间点到达j的路径条数。以此类推,如果是矩阵的N次幂,得到结果矩阵x,那么x[i][j]表示从i出发,经过N个中间点到达j的方案数。这里要注意所谓的邻接矩阵其实是01矩阵,即表示两点之间是否连边。然后本题就是要求类似这样的一个问题。
然后不同之处在于,本题求的是经过T步以及T步以下步骤从起点到达终点的方案数,当时一时半会儿没有想到如何用快速幂解决小于T步的问题。其实后来想想,只需要再连一条边从终点N出发到达N,即自环。这样子对于那些在T步前已经到达终点的点我们就可以让他在终点处打转,最后在计算T步的方案数的时候也把他计算了进去。当然这有个前提条件,就是到达了终点之后不再离开终点,这个题目说明了到达了终点就不能够再离开终点。那么我们在建立邻接矩阵加边的时候就要注意终点没有除自环之外的出边,这样我们就能保证不会离开终点。直接用矩阵快速幂即可。
现在想起来还是无比的后悔,仅仅七十几行代码啊……惨痛的教训,但从哪跌倒从哪站起来,WHU,雪耻之战!ALPC_NeverGiveup……
#include
#include
#include
#include
#include
#include
#include
#define LL long long
using namespace std;
struct matrix
{
long long a[101][101];
} x,basic,ans;
int n,m,t;
LL y;
matrix matmulti(matrix x,matrix y)
{
matrix ans;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
ans.a[i][j]=0;
for(int k=1;k<=n;k++)
{
ans.a[i][j]+=(x.a[i][k]*y.a[k][j])%1000000007;
ans.a[i][j]%=1000000007;
}
}
return ans;
}
matrix matpow(matrix x,LL y)
{
if (y==0) return basic;
else
while ((y&1)==0)
{
y>>=1;
x=matmulti(x,x);
}
matrix ans=x;
y>>=1;
while (y!=0)
{
x=matmulti(x,x);
if ((y&1)!=0) ans=matmulti(ans,x);
y>>=1;
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) basic.a[i][i]=1;
for(int i=1;i<=m;i++)
{
int u,v; scanf("%d%d",&u,&v);
if (u==n) x.a[v][u]=1;
else if (v==n) x.a[u][v]=1;
else x.a[u][v]=x.a[v][u]=1;
}
scanf("%d",&t);
x.a[n][n]=1;
x=matpow(x,t);
printf("%lld",x.a[1][n]);
}