列表

详情


NC16605. 寻宝

描述

由依是战线佯攻部队的辅助人员,在岩泽消失之后,企图代替岩泽成为GDM主唱。但是SSS战线的领袖仲村由理是不会轻易让她加入的,于是由理子给了由依一项艰巨的任务:去一个地下迷宫寻找宝石!
这个迷宫由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,表示测试组数。
每个测试用例前面都有一个空白行。
每个测试用例包含四个整数a,b,c和n。

输出描述

对于每个测试用例输出一个数表示她可以从迷宫中获取的最大宝石数量。

示例1

输入:

3

1  2  0  64

0  2  1  47

0  3  5  128

输出:

5
23
64

说明:

起点很重要。例如,假设在第一个例子中,由依从 0号房间 开始测试。她的两个选择是通向房间0的通道和通往迷宫外的通道 。更好的策略是从2号房间开始并沿着路径 2 → 8 → 16 → 32 → 0 → 出口。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 2832ms, 内存消耗: 193632K, 提交时间: 2018-08-06 20:36:30

#include<bits/stdc++.h>
using namespace std;
const int maxn=(1<<24)+5;
int dp[maxn],vis[maxn],to[maxn];
int ans,a,b,c,n;
void dfs(int u)
{
    vis[u]=1;
    int v=to[u];
    if(!vis[v])dfs(v);
    else if(vis[v]==1)vis[v]=3;
    dp[u]=dp[v]+1;
    if(vis[u]==3)
    {
        int w=v;
        while(w!=u)
        {
            dp[w]=dp[u];
            w=to[w];
        }
    }
    vis[u]=2;
}
void solve()
{
    scanf("%d%d%d%d",&a,&b,&c,&n);
    ans=0;
    for(int i=0;i<n;i++)
    {
        dp[i]=0;vis[i]=0;
    }
    for(int i=0;i<n;i++)
    {
        int pos=(1ll*a*i*i+b*i+c)%n;
        to[i]=pos;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[i])dfs(i);
        ans=max(ans,dp[i]);
    }
    printf("%d\n",ans);
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)solve();
    return 0;
}

C++(clang++11) 解法, 执行用时: 1480ms, 内存消耗: 193656K, 提交时间: 2020-12-16 21:15:58

#include<bits/stdc++.h>
using namespace std;

int R[17000005],DP[17000005],V[17000005];
void DFS(int x)
{
	int i=R[x];
	if(!V[i])V[i]=1,DFS(i);
	else if(V[i]==1)V[i]=3;
	DP[x]=DP[i]+1;
	if(V[x]==3)while(i!=x)DP[i]=DP[x],i=R[i];
	V[x]=2;
}
int main()
{
    int i,j,x,y,n,ans,T;
    long long a,b,c;
    scanf("%d",&T);
    while(T--)
    {
    	scanf("%lld%lld%lld%d",&a,&b,&c,&n),ans=0;
    	for(i=0;i<n;i++)R[i]=(a*i*i+b*i+c)%n,V[i]=DP[i]=0;
		for(i=0;i<n;i++)if(!V[i])V[i]=1,DFS(i),ans=max(ans,DP[i]);
    	printf("%d\n",ans);
	}
	return 0;
}

上一题