(矩阵快速幂) [TJOI2017]可乐

这题一看我就先想着t*m的分层图dp,dp[i][j][k]代表第t秒第j个点的路径数,k=0就是在第j个点爆炸,k=1就是停留在j点,然后

dp[i][j][1]=dp[i-1][j][1]+∑(其他相邻点v,dp[i-1][v][1]),意思是第i秒停留在第j个点的路径可以是第i-1秒停留在第j个点或和j相邻点转移过来

dp[i][j][0]=dp[i-1][j][1],意思是在第i秒第j个点爆炸的点只能是第i-1秒停留在第j个点转移来

然后把每秒爆炸的方案加上,再加上第t秒停留在每个点的方案就是答案

然后我就是开始写了。。然后样例过了。。然后我就开始交。。。然后人没了

一直t一直t,t到怀疑人生

然后我就试了下题解的分层dp代码,然后也t了,应该是加强了数据。告辞

(话说洛谷评测机真8太行,1s1e8都跑不了)

那就只能矩阵快速幂了,邻接矩阵的k次幂的到mp[][],mp[i][j]意思是第i个点到第j个点路径长度为k的走法有多少种

于是这题不就是要求点1走t次到其他点的总方案吗

不过还有两个地方要处理

1.它可以在某个点停留

那我们只要给每个点增加一个自环,那就可以达到在某个点停留的效果

2.它可以自爆

那只要给每个点和0连一条边,0本身没有出边,那每个点到0就不能出去,相当于自爆了

最后ans=  \sum_{i=0}^{n}mp[1][i],

题目描述

加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的 111 号城市上。这个可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆。它每一秒都会随机触发一种行为。现在给加里敦星球城市图,在第 000 秒时可乐机器人在 111 号城市,问经过了 ttt 秒,可乐机器人的行为方案数是多少?

输入格式

第一行输入两个正整数 NNN,MMM。NNN 表示城市个数,MMM 表示道路个数。

接下来 MMM 行每行两个整数 uuu,vvv,表示 uuu,vvv 之间有一条道路。保证两座城市之间只有一条路相连,且没有任何一条道路连接两个相同的城市。

最后一行是一个整数 ttt,表示经过的时间。

输出格式

输出可乐机器人的行为方案数,答案可能很大,请输出对 201720172017 取模后的结果。

输入输出样例

输入 #1

3 2
1 2
2 3
2

输出 #1

8

说明/提示

样例输入输出 1 解释

  • 111 ->爆炸。
  • 111 -> 111 ->爆炸。
  • 111 -> 222 ->爆炸。
  • 111 -> 111 -> 111。
  • 111 -> 111 -> 222。
  • 111 -> 222 -> 111。
  • 111 -> 222 -> 222。
  • 111 -> 222 -> 333。

数据范围与约定

  • 对于 20%20\%20% 的数据,保证 t≤1000t \leq 1000t≤1000。
  • 对于100%100\%100%的数据,保证 1#include #include #include #include using namespace std; typedef long long ll; const ll mod = 2017; mapmp; inline ll read(){ ll x = 0;char c = 0; c = getchar(); while(isdigit(c)) x = (x<<1)+(x<<3)+(c^48),c = getchar(); return x; } struct matrix{ ll x[31][31]; }a; matrix muli(matrix a,matrix b){ matrix temp; memset(temp.x,0,sizeof(temp.x)); for(register int i = 0; i <=30; i++) for(register int j = 0; j <=30; j++) for(register int k = 0; k <=30; k++){ temp.x[i][j]+=a.x[i][k]*b.x[k][j]; temp.x[i][j]%=mod; } return temp; } matrix pows(matrix a,ll b){ matrix e; memset(e.x,0,sizeof(e)); for(register int i = 0; i <=30; i++) e.x[i][i] = 1; matrix ans = e; while(b){ if(b&1) ans=muli(ans,a); a=muli(a,a); b>>=1; } return ans; } int main() { /*ll n,q; q = read(),n = read(); matrix a; a.x[0][0] = 3;a.x[0][1] = 1;a.x[1][0] = 1;a.x[1][1] = 0; matrix b; b.x[0][0] = 3;b.x[0][1] = 1;b.x[1][0] = 2;b.x[1][1] = 0; ll ans = 0; matrix a1,b1; mp[0] = 0;mp[1] = 1; for(register ll i = 1; i <= q; i++){ if(mp.count(n)==0){ b1=pows(b,n-2); a1=muli(a,b1); ans=ans^a1.x[0][0]; mp[n] = a1.x[0][0]; n=n^(a1.x[0][0]*a1.x[0][0]); }else{ ans^=mp[n]; n^=(mp[n]*mp[n]); } } printf("%lld\n",ans);*/ ll n,m; scanf("%lld %lld",&n,&m); for(ll i=1;i<=m;i++) { ll u,v; scanf("%lld %lld",&u,&v); a.x[u][v]=1;a.x[v][u]=1; } for(ll i=0;i<=n;i++)a.x[i][i]=1; for(ll i=1;i<=n;i++) { a.x[i][0]=1; } ll t; scanf("%lld",&t); matrix b=pows(a,t); ll ans=0; for(ll i=0;i<=n;i++) ans=(ans+b.x[1][i])%2017; printf("%lld\n",ans); return 0; }

     

 

你可能感兴趣的:(快速幂,1000篇,洛谷)