题意:相信以看官大佬的水平看懂题面应该没什么问题吧,,我就不概括了才不是因为我概括不出来呢
本来我想的是整个图跑一下,记录一下环(一直走肯定会陷入一个环里面的),但发现假如有一条路穿过整个图,然后陷入一个小环里面,那么在前面就要花n的时间来求前面的边,想想肯定会挂。于是膜了一个不知名的dalao(还是被爬虫网站抓过去的,源地址根本找不到。。)
正解是倍增。
f[i][j][k]表示从i号点沿j字母走2k步的收益
g[i][j][k]表示从i号点沿j字母走2k步后的位置
然后
f[i][j][k]=f[i][j][k-1]+f[g[i][j][k-1]][j][k-1]
g[i][j][k]=g[g[i][j][k-1]][j][k-1]
代码:
#include<bits/stdc++.h>
using namespace std;
int n,K,mod,now=1,ans=0,f[10010][30][32],g[10010][30][32];//f[i][j][k]:在i点沿着j字母跳2^k步的收益,g[i][j][k]:在i点沿着j字母跳2^k步的位置
char s[120010];
int main()
{
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++)
{
for(int j=0;j<K;j++)
{
int a,b;
scanf("%d%d",&a,&b);
f[i][j][0]=b;
g[i][j][0]=a;
}
}
scanf("%s%d",s,&mod);
for(int k=1;k<32;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=0;j<K;j++)
{
f[i][j][k]=(f[i][j][k-1]+f[g[i][j][k-1]][j][k-1])%mod;
g[i][j][k]=g[g[i][j][k-1]][j][k-1];
}
}
}
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]=='[')
{
int nn=0;
i++;
while(s[i]>='0'&&s[i]<='9')
{
nn=nn*10+s[i]-'0';
i++;
}
int hh=s[i]-'A';
// printf("%d %d\n",nn,hh);
for(int j=31;j>=0;j--)
{
if((1u<<j)<=nn)
{
nn-=(1<<j);
ans=(ans+f[now][hh][j])%mod;
now=g[now][hh][j];
// printf("f[%d][%d][%d]=%d\n",now,hh,j,f[now][hh][j]);
}
}
i++;
}
else
{
ans=(ans+f[now][s[i]-'A'][0])%mod;
now=g[now][s[i]-'A'][0];
}
// printf("%d\n",ans);
}
printf("%d",ans);
}