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

P2151 [SDOI2009] HH去散步 题解

时间:2023-08-26 16:12:40浏览次数:47  
标签:方案 P2151 题解 ll 矩阵 条边 const SDOI2009 jgt

传送门

简要题意:有\(n\)个人,\(m\)条无向边,走\(e\)条边,满足条件若第\(i\)条边为\(u->v\)则第\(i+1\)条边不能是\(v->u\),问\(s->t\)的方案有多少个,取模45989。

因为要满足题目关于边的条件,所以我们考虑点边互换

将\(u-v\)的无向边一分为二变成\(u->v,v->u\),第\(i\)条边记录两个变量为\(i.from,i.to\),表示\(i\)从\(i.from\)到\(i.to\)的边,他们互为反边

则从第\(i\)条边走到第\(j\)条边的条件是\(i.to=j.from\)

先考虑用动态规划思考转移方程:

\(f_{i,j}\)表示第\(i\)个时刻走到第\(j\)条边的方案

\(f_{i,j}=\sum\limits_{k=1}^{2m}f_{i-1,k}*a_{k,j}\),其中若第\(k\)条边可以走到第\(j\)条边则\(a_{k,j}=1\),否则为\(0\)。

因为\(e\)很大,所以我们要考虑矩阵乘法

构造转移矩阵\(B\)满足\(B_{i,j}\)表示第\(i\)条边到第\(j\)条边的方案。则\(B_{i,j}=1\)的情况为\(i.to=j.from\)且\(i\)与\(j\)不能互为反边

构造初始矩阵\(A\),\(A_{i,j}\)表示第\(i\)条边到第\(j\)条边的方案。则\(A_{i,j}=1\)的条件时\(i.to=j.from=s\),注意这里有个细节,因为我们是从\(s\)点而不是走某一条边开始走,所以我们不分正反边且只需枚举一个\(i.to=s\)的情况表示从\(s\)开始走即可。

若\(Ans_{i,j}\)表示最终从第i条边走到第\(j\)条边的方案数。如果\(i.to=s\)且\(j.to=t\),则\(ans+=Ans_{i,j}\)

上代码:

#include<bits/stdc++.h>
#define ll long long
#define PLL pair<ll,ll> 
using namespace std;
const ll M=130,mod=45989;
ll n,m,ti,s,t,flag;
ll u,v,idx,ans;
struct fu
{
	ll from,to;
}bian[200];
struct jgt
{
	ll a[M][M];
}A,B;
jgt operator * (const jgt t1,const jgt t2)
{
	jgt t={0};
	for(ll i=0;i<=idx;i++)
	for(ll j=0;j<=idx;j++)
	for(ll k=0;k<=idx;k++)
	t.a[i][j]=(t.a[i][j]+(t1.a[i][k]*t2.a[k][j])%mod)%mod;
	return t;
}
void sc(jgt t1)
{
	printf("输出:\n");
	for(ll i=0;i<=idx;i++)
	{
		for(ll j=0;j<=idx;j++)
		printf("%lld ",t1.a[i][j]);
		printf("\n");
	}
	printf("输出完毕!\n"); 
}
int main()
{
	scanf("%lld %lld %lld %lld %lld",&n,&m,&ti,&s,&t);
	for(ll i=1;i<=m;i++)
	{
		scanf("%lld %lld",&u,&v);
		bian[idx++]={u,v};
		bian[idx++]={v,u};
	}
	idx--,ti--;
	for(ll i=0;i<=idx;i++)
	for(ll j=0;j<=idx;j++)
	if(bian[i].to==bian[j].from&&j!=i&&j!=(i^1)) B.a[i][j]=1;
	for(ll i=0;i<=idx;i++)
	{
		for(ll j=0;j<=idx;j++)
		if(bian[i].to==bian[j].from&&bian[j].from==s) A.a[i][j]=1;
		if(bian[i].to==s)
		{
			flag=i;
			break;
		}
	}
	while(ti)
	{
		if(ti&1) A=A*B;
		B=B*B;
		ti=ti/2;
	}
	for(ll j=0;j<=idx;j++)
	if(bian[j].to==t) ans=(ans+A.a[flag][j])%mod;
	printf("%lld\n",ans);
	return 0;
}

标签:方案,P2151,题解,ll,矩阵,条边,const,SDOI2009,jgt
From: https://www.cnblogs.com/pengchujie/p/17658937.html

相关文章

  • 【题解】CF1413C Perform Easily(双指针)
    【题解】CF1413CPerformEasily写篇题解水水经验~顺便增加一下RP~比较套路和简单的一道绿题。题目链接PerformEasily-洛谷|计算机科学教育新生态(luogu.com.cn)题意概述给你一个长度为\(6\)的\(a\)数组,和一个长度为\(n\)的\(b\)数组,要求将\(b\)数组内的每......
  • [CF1794E] Labeling the Tree with Distances 题解
    [CF1794E]LabelingtheTreewithDistances题解题目描述给你一个树,边权为\(1\)。给定\(n-1\)个数,你需要将这些数分配到\(n-1\)个节点上。一个点\(x\)是好的,当且仅当存在一种分配方案,所有被分配数的点到\(x\)的最短路径长度等于其被分配的数。求所有好点。思路从......
  • 1.2 金字塔原理-构建金字塔原理与问题解决
    一、构建金字塔原理与问题解决1.自上而下2.自下而上3.解决问题的过程界定问题详细描述问题的背景信息用SMART原理定义目标明确想要达到的成果以及衡量成功与否的标准分解问题关键分析以假设和最终结果为导向反复地进行假设和数据分析尽可能地简化分......
  • 网络规划设计师真题解析--IP地址(二)
    地址202.118.37.192/26是(25),地址192.117.17.255/22是(26)。(2018年真题)(25)A.网络地址B.组播地址C.主机地址D.定向广播地址(26)A.网络地址B.组播地址C.主机地址D.定向广播地址答案:(25)A(26)C解析:(25)202.118.37.192/26,建网比特数为/26,前三字节为24位,光看最后一字节192......
  • wmctf的题解&&blindless&&exit_hook
    0x00好久不见2023.8.23夜里wm2023也是一个收获很大的比赛。只做了一个blindless,但是体会到了无泄露做出题来的奥妙。踩过的坑(学到的东西)包括但不限于调试要用docker,不然没符号表很痛苦有想法一定要及时记下来,很有可能是解题重点exit_hook的n种姿势(下面记录一下......
  • P4327题解
    思路分组计算以下图为例:..#...#...*...#...#.#.#.#.*.*.#.#.#.X.#.X.*.X.*.X.#.#.#.#.#.*.*.#.#...#...#...*...#..我们可以发现每个图形的第1、2、4、5排均是同样的图形,可我们仔细观察第3排:#.X.#.X.*.X.*.X.#只有第一个图形是完整的(或者说对称)附图:#......
  • 牛客练习赛114 D题题解
    比赛编号太臭了题目链接对一第一组数据,我们形象化的得到下图:如何拆解使其变成一个“顺子”呢,我们像这样:贪心的从后往前取,对于取数列时的终点也就是枚举的起点如果不为0,就向前一直取,如果取到一个数\(x\)发现这个数的个数\(num_x\)是大于\(num_{x-1}\)的,就停止,最后看拆......
  • P9166题解
    简单题,但是我考场写炸了。\(100\rightarrow70\)。我们读入的时候,先开两个数组\(ls,rs\)来记录当前这个点是否为某条线段左端点或右端点。我们发现,每一条线段都是连续的,因此可以直接差分记录当前这个点能否走到。然后你提交上去发现你能过。实际上这种做法是假的。为什么呢?......
  • ABC296D题解
    简单题。考虑-1的情况,即为\(n^2<m\)。剩下暴力枚举\(a\)即可。上限为\(\sqrt{m}+1\)。注意要\(+1\),因为上取整(本人赛时被这个罚了很多次)。可以由\(m\)和\(a\)确定\(b\)的最小值,即\(b=\lceil\frac{m}{a}\rceil\)。注意卡longlong以及\(a,b\)的最大值不能超......
  • AT_donuts_2015_3 题解
    根据题意,发现我们要维护一个身高递减的序列。因此,我们可以直接使用单调栈维护第\(i\)个人能看到的人数即可。答案就是当前栈内的元素数量。注意应先输出答案再将当前高度入栈。#include<cstdio>intn;inth[100010];intst[100010];inttop;intmain(){ scanf("%d",&......