Nowcoder 牛客练习赛 20 C


题意:这个迷宫由n个房间组成,编号为0到n - 1,每个房间里都有一颗宝石,房间通过单向通道连接。每个房间里有两个门:一个通向第R个房间(R=(a·v2 + b·v + c) mod n),另一个通向迷宫出口,一旦离开迷宫,便会触发自毁机关,将再也没有机会继续收集宝石。现在,她可以在任何地点进入迷宫,沿隧道移动并收集宝石。

由依想尽可能地收集宝石,你能算出她能从迷宫中获得的最大宝石数量是多少吗?
ps:(a·v+ 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);
    }
}

猜你喜欢

转载自www.cnblogs.com/Pedestrian6/p/9191990.html