首页 > 其他分享 >[题解]P2151 [SDOI2009] HH去散步

[题解]P2151 [SDOI2009] HH去散步

时间:2024-11-22 16:07:07浏览次数:1  
标签:head P2151 MM 题解 矩阵 int add SDOI2009 define

P2151 [SDOI2009] HH去散步

发现\(n,m\)非常小而\(t\)非常大,所以果断考虑矩阵。

这道题如果不限制“不能立即沿刚刚过来的路回去”,就直接用邻接矩阵求\(t\)次幂然后直接调用\(ans[a][b]\)就好了。

加上限制后,我们用点就比较难考虑了,因为点是无方向的。

我们可以试着用边来转移,和点相同地,每条边记录自己可以直接到达哪些边,只需要额外限制不能走自己的反边回去即可。将\(F[i][j]\)作为转移矩阵,表示边\(i\)到边\(j\)的路径数量。初始时,对于\(u,v\)两条满足条件的边,令\(F[u][v]=1\)。

将\(G\)作为初始矩阵,点\(a\)的邻接边都设为\(1\),用\(G\times F^{t-1}\)统计答案即可。除了转点为边以外,其他做法与点均没什么区别。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define mod 45989
#define N 52
#define MM 122
using namespace std;
struct edge{int nxt,to;}e[MM];
int n,m,t,a,b,idx,head[N],base[MM][MM],ans[MM][MM],tmp[MM][MM],res;
void add(int u,int v){e[idx]={head[u],v},head[u]=idx++;}
void mul(int to[MM][MM],int a[MM][MM],int b[MM][MM]){
	memset(tmp,0,sizeof tmp);
	for(int i=0;i<idx;i++) for(int j=0;j<idx;j++) for(int k=0;k<idx;k++)
		tmp[i][j]+=(a[i][k]*b[k][j])%mod,tmp[i][j]%=mod;
	memcpy(to,tmp,sizeof tmp);
}
void qpow(int n){
	while(n){
		if(n&1) mul(ans,ans,base);
		mul(base,base,base),n>>=1;
	}
}
signed main(){
	memset(head,-1,sizeof head);
	cin>>n>>m>>t>>a>>b;
	for(int i=1,u,v;i<=m;i++)
		cin>>u>>v,add(u,v),add(v,u);
	for(int i=0;i<idx;i++)
		for(int j=head[e[i].to];~j;j=e[j].nxt)
			if(j!=(i^1)) base[i][j]=1;
	for(int i=head[a];~i;i=e[i].nxt) ans[0][i]++;
	//这里选[0,idx)哪一个值作为答案的行都可以,qpow会将此行保留,其他行置为0
	qpow(t-1); 
	for(int i=head[b];~i;i=e[i].nxt) res+=ans[0][i^1],res%=mod;
	cout<<res;
	return 0;
}

还有一种方法,将所有节点下标\(+1\),建立节点\(0\)向\(a\)连一条边\(u\),这样\(F\)就增加了\(1\)维。此时\(F^t\)的第\(0\)行即为答案。这是因为此时的初始矩阵只有\(G[0]=1\),所以用\(G\)乘这一步可以直接省去。就不放代码了。

标签:head,P2151,MM,题解,矩阵,int,add,SDOI2009,define
From: https://www.cnblogs.com/Sinktank/p/18562975

相关文章

  • CF1375题解
    CF评分2693,豆瓣拒绝评分,这套题啥实力就不用说了CF1375A被爆切了(悲,md想了20分钟没有想出来,然后就看了一眼题解,wc这不直接一正一负就解决了吗。。。脑子不转了CF1375B切了,首先有一组必然合法的解,就是把所有数都变为大于0的数,这样必然是最大的解,若\(a[i]\)还有比这组解大的就......
  • Atcoder Regular Contest 061 题解
    ARC061C.ManyFormulas*1089首先预处理出原数区间\([i,j]\)所代表的真实数字。然后注意到\(|s|\leq10\),所以直接爆搜回溯最后判断即可。或者状压枚举也可以,反正非常简单。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;strings;LLSum[11][11]......
  • 2024考前集训测试37 错峰旅行 题解
    题目描述小Z终于迎来了自己的大学生活最后的时刻,他决定用自己的积蓄来一场说走就走的毕业旅行,并且不玩的开心不上班。然而,他很快就发现这个决定并非那么简单。由于是暑假,假期人多,他既不想错过旅行的最佳时期,又不想在人群中挣扎,预测旅游热门城市的拥挤时段,就像是一道难题摆在他......
  • ybtoj 高效进阶题解索引
    密码:sunxuhetai2009--------------------云落的分割线--------------------基础算法第1章-递推算法第2章-贪心算法--------------------云落的分割线--------------------图论第1章-并查集第4章-强连通分量--------------------云落的分割线--------------------......
  • Winform跨线程访问报错问题解决
    `usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;namespaceWinf......
  • [JOI 2022 Final] 让我们赢得选举 (Let's Win the Election) 题解
    [JOI2022Final]让我们赢得选举(Let'sWintheElection)/選挙で勝とう(Let'sWintheElection)首先由\[\min\left(\fracab,\fraccd\right)\le\frac{a+c}{b+d}\le\max\left(\fracab,\fraccd\right)\]得出,集中力量办大事,得到的支持者一定要和本人在同一州进行演讲。......
  • [COCI2015-2016#6] PAROVI | 互质覆盖 题解
    前言不能在同一个坑上栽第三次!题目链接:原题;加强版。题意简述\(1\simn\)数轴,你可以使用若干条线段\([l,r]\)来覆盖,其中要满足\(\gcd(l,r)=1\)。问你能够完全覆盖数轴的方案数,对\(M\)取模。\(2\leqn\leq10^4\),\(2\leqM\leq10^9+7\)。不保证\(M\)为质数。......
  • 【题解】AT_joisc2007_mall ショッピングモール (Mall)
    原题传送门温馨提示:岛国题要换行!需要求一个矩阵的和,考虑二维前缀和。题目中不允许矩阵中有负数,结合求和的最小值,我们把负数赋为最大值不就行了吗。接下来就是求二维前缀和了。基于容斥原理,二维前缀和有如下递推关系:\[sum_{i,j}=sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1}+c_{i......
  • 【题解】AT_agc011_b [AGC011B] Colorful Creatures
    原题传送门我们知道,要想使一个生物能活到最后,那么它进行的每一次吸收前,它的大小应当尽可能大,所以我们考虑贪心,对生物的大小从小到大排序,每个生物都从小的开始吸收,看能不能活到最后,时间复杂度\(\mathcal{O(n^2)}\)。我们还知道,排序后,生物\(i\)能活到最后,则生物\(i+1\simn\)......
  • P7906 [Ynoi2005] rpxleqxq 题解
    P7906[Ynoi2005]rpxleqxq题解题目大意给定一个长度为\(n\)的序列\(A\),和一个常数\(k\)。有\(m\)次询问,每次给定一个区间\([l,r]\),询问有多少二元组\((i,j)\),满足:\(1\leqi<j\leqn\);\((A_i\oplusA_j)\leqk\)。Solve前置知识:莫队二次离线。对于普通莫队,端......