BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)
首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。
PS:WA了N久改了3次终于A了QAQ
CODE:
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define mod 45989using namespace std;struct mat{ int n,m; long long a[122][122]; mat(){n=m=0;memset(a,0,sizeof(a));} int I(int _x){n=m=_x;for (int i=1;i<=n;i++) a[i][i]=1;}};mat operator *(const mat x,const mat y){ mat ans; ans.n=x.n;ans.m=y.m; for (int i=1;i<=x.n;i++) for (int j=1;j<=y.m;j++) for (int k=1;k<=x.m;k++) (ans.a[i][j]+=x.a[i][k]*y.a[k][j])%=mod; return ans;}mat power(mat x,long long y){ mat ans;ans.I(x.n); for (;y;y>>=1){ if (y&1) ans=ans*x; x=x*x; } return ans;}struct edges{ int id,to,next;}edge[123];int l,next[23];int addedge(int from,int to,int id){ edge[++l]=(edges){id,to,next[from]}; next[from]=l;}int main(){ int n,m,a,b; long long t; mat x; scanf("%d%d%lld%d%d",&n,&m,&t,&a,&b); x.n=x.m=m*2; a++;b++; for (int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); x++;y++; addedge(x,y,i); addedge(y,x,i+m); } for (int i=1;i<=n;i++) for (int j=next[i];j;j=edge[j].next) for (int k=next[edge[j].to];k;k=edge[k].next) if (abs(edge[j].id-edge[k].id)!=m) x.a[edge[j].id][edge[k].id]=1; x=power(x,t-1); int q=t&1==1?1:0; long long ans=0; for (int i=next[a];i;i=edge[i].next) for(int j=1;j<=l;j++) if (edge[j].to==b) (ans+=x.a[edge[i].id][edge[j].id])%=mod; printf("%lld",ans); return 0;} |
浙公网安备 33010602011771号