题意:这个迷宫由n个房间组成,编号为0到n - 1,每个房间里都有一颗宝石,房间通过单向通道连接。每个房间里有两个门:一个通向第R个房间(R=(a·v2 + b·v + c) mod n),另一个通向迷宫出口,一旦离开迷宫,便会触发自毁机关,将再也没有机会继续收集宝石。现在,她可以在任何地点进入迷宫,沿隧道移动并收集宝石。
由依想尽可能地收集宝石,你能算出她能从迷宫中获得的最大宝石数量是多少吗?
ps:(a·v2 + b·v + c) mod n表示第v个门通向第(a·v2+b·v+c)%n个门
T<=10,保证满足n>300的最多两组
n≤224
sol
可以观察到每个点出度为1,所以图中只有环和有链接进来的环,并且环一定是终点因为进去出不来,所以就预处理出所有的环,环上的点的最大延伸长度就是环长,然后就处理链,从离链终点(环)由近到远最大延伸长度+1
#include<iostream> #include<cstdio> #include<cstring> #define N (20001010) #define LL long long using namespace std; int a,b,c,To[N],n,A[N],tp,St[N]; bool vis[N]; int fic(int x){ LL res=((LL)a*(LL)x*(LL)x+(LL)b*(LL)x+(LL)c)%(LL)n; return (int)res; } int main(){ int Test_num; cin>>Test_num; while (Test_num--){ scanf("%d %d %d %d",&a,&b,&c,&n); int i,j; for (i=0;i<n;i++) To[i]=fic(i),A[i]=0,vis[i]=0; for (i=0;i<n;i++) if (!vis[i]){ tp=0; vis[i]=1; St[++tp]=i; while (1){ St[tp+1]=To[St[tp]]; tp++; if (vis[St[tp]]){ if (!A[St[tp]]){ for (j=tp-1;j>=1;j--) if (St[j]==St[tp]) break; int pos=j; for (j=pos+1;j<=tp;j++) A[St[j]]=tp-pos; tp=pos; } tp--; while (tp>0){ A[St[tp]]=A[St[tp+1]]+1; tp--; } break; } vis[St[tp]]=1; } } int res=0; for (i=0;i<n;i++) res=max(res,A[i]); printf("%d\n",res); } }