zoukankan      html  css  js  c++  java
  • geronimo

    时间限制 1s 空间限制 512MB

    3.1 题目描述

    “Geronimo∼”
    时间还很多,让我们慢慢来。
    不如听首开心的歌再看题?…… 算了,直接看题吧。
    给定一个整数 n,以及一个 n 阶的排列 p 1 , p 2 , …, p n 。
    我们定义重组过程如下:如果当前的排列是 a 1 , a 2 , …, a n ,经过一次重组,就会
    变成 p a 1 , p a 2 , …, p a n 。
    问一个排列至少要经过多少次重组才会恢复成重组前的状态。
    由于答案可能很大,输出其对一个给定的正整数 q 取模的值即可。

    3.2 输入格式

    第一行两个正整数 n, q。
    第二行一共 n 个整数,依次表示 p 1 , p 2 , …, p n 。
    同一行相邻的数间用一个空格隔开。

    3.3 输出格式

    一行一个整数,表示答案对 q 取模的值。

    3.4 样例输入

    7 1000000207
    2651347

    3.5 样例输出

    4

    3.6 数据规模和约定

    对于全部的数据,q ≤ 2 × 10 9
    对于 10% 的数据,q = 1
    对于另外 20% 的数据,n ≤ 9
    6对于另外 40% 的数据,n ≤ 10 3
    对于剩下 30% 的数据,n ≤ 5 × 10 5

    【题解】

    这道题就是找出每个点恢复初始状态的步数(或者称为找个环),再求出这些步数的最大公约数即可。
    (然而我考试时打了个愚蠢的10分暴力)
    但注意有几点优化:
    1、一个环上所有点恢复初始状态的步数相同(解决TLE问题)
    2、求一群数的最大公约数,可以一一找出每一对数,求出两个数的最大公约数,再用后一个数除掉(用前一个数的话就是改掉当前搜索的数,会wa7个点),最后把剩下的数连乘即可。(另一种思路是线性筛打表出素数,看每个数的质因子)
    3、恢复初始状态的步数相同的点的步数可去重,这里我用的是map(和vis一样)。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #define ll long long
    #define re register
    #define il inline
    #define fp(i,a,b) for(re ll i=a;i<=b;i++)
    #define fq(i,a,b) for(re ll i=a;i>=b;i--)
    using namespace std;
    ll a[500005]={},c[500005]={},total=0;
    bool vis[500005]={};
    map<ll,ll>b;
    il ll gi()
    {  
      re ll x=0;
      re ll t=1;
      re char ch=getchar();
      while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    ll gcd(ll x,ll y)
    {
        if(y==0) return x;
        return gcd(y,x%y);
    }
    int main()
    {
        freopen("geronimo.in","r",stdin);
        freopen("geronimo.out","w",stdout);
        ll n=gi(),q=gi();
        if(q==1) {printf("0
    ");return 0;}
        fp(i,1,n)
            a[i]=gi();
        fp(i,1,n)
            if(vis[i]==0)
        {
            ll j=a[i],sum=1;
            while(j!=i) sum++,j=a[j];
            j=a[i];
            while(j!=i) vis[j]=1,j=a[j];
            if(b[sum]==0) b[sum]=1,c[++total]=sum;
        }
        fp(i,1,total-1)
            fp(j,i+1,total)
        {
            ll x=c[i],y=c[j];
            if(x<y) swap(x,y);
            ll r=gcd(x,y);
            c[j]/=r;//beach,c[i]/=i会wa7个点,因为不能改当前数
        }
        ll ans=1;
        fp(i,1,total)
            ans=(1ll*ans*c[i])%q;
        printf("%lld
    ",ans);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    【k8s】pv 处在 Terminating 状态
    【k8s】命令行自动补全
    【k8s】允许 master 节点运行 pod
    【k8s】Harbor 安装
    Nginx 允许 frame 嵌套
    Python基础教程:json中load和loads区别
    Python 基础教程:用户交互语句
    Python正则表达式-常用函数的基本使用
    Python字典循环与字典排序
    4道Python文件操作和函数练习题
  • 原文地址:https://www.cnblogs.com/yanshannan/p/7375734.html
Copyright © 2011-2022 走看看