• hdu 5392 Infoplane in Tina Town(数学)


    Problem Description
    There is a big stone with smooth surface in Tina Town. When people go towards it, the stone surface will be lighted and show its usage. This stone was a legacy and also the center of Tina Town’s calculation and control system. also, it can display events in Tina Town and contents that pedestrians are interested in, and it can be used as public computer. It makes people’s life more convenient (especially for who forget to take a device).
    Tina and Town were playing a game on this stone. First, a permutation of numbers from 1 to n were displayed on the stone. Town exchanged some numbers randomly and Town recorded this process by macros. Town asked Tine,”Do you know how many times it need to turn these numbers into the original permutation by executing this macro? Tina didn’t know the answer so she asked you to find out the answer for her.
    Since the answer may be very large, you only need to output the answer modulo 3230+1=3221225473 (a prime).
     
    Input
    The first line is an integer T representing the number of test cases. T5
    For each test case, the first line is an integer n representing the length of permutation. n3106
    The second line contains n integers representing a permutation A1...An. It is guaranteed that numbers are different each other and all Ai satisfies ( 1Ain ).
     
    Output
    For each test case, print a number ans representing the answer.
     
    Sample Input
    2 3 1 3 2 6 2 3 4 5 6 1
     
    Sample Output
    2 6
     

    中文题目:

    Tina Town 的镇中有一块表面平整光滑的大石头, 当人面向它走进时, 石头的表面就会亮起, 显示出它的用途. 这块石头是前人留下来的东西,是Tina Town算力和控制系统的核心, 同时它也可以显示Tina Town的大小事和行人关注的内容,也可以作为公共的计算机使用 ,极大地方便了人们的生活(特别是上街忘带终端的人们啦).
    
    Tina和Town在这块大石头上玩一个游戏. 石头上首先显示出了1到n排列的n个数,Town则随机交换了一些数, 然后Town通过宏将这个交换的过程记录下来了. Town 问 Tina: 你知道执行几次这个宏, 这些数会恢复最早的排列嘛? Tina是一个蠢蠢的女孩子, 当然不知道啦, 于是她想向你请教呢.
    


    来自官方题解:

    给出一个置换,求它的循环长度。数据范围 3 imes 10^63×106​​。

    其实没有什么好说的,就分解成循环求长度的最小公倍数就好了。对于这个模数要用unsigned int存,这个最小公倍数的求法不能用欧几里得,直接每次分解质因数,用线性筛预处理一下就好了。

     

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<set>
     6 #include<map>
     7 #include<cmath>
     8 #include<stdlib.h>
     9 using namespace std;
    10 #define ll long long 
    11 #define N 3000006
    12 #define MOD 3221225473
    13 int n;
    14 int a[N];
    15 int vis[N];
    16 int cou[N];
    17 inline int sca()     //输入外挂
    18 {
    19       int res=0,ch,flag=0;
    20       if((ch=getchar())=='-')
    21           flag=1;
    22       else if(ch>='0'&&ch<='9')
    23           res=ch-'0';
    24       while((ch=getchar())>='0'&&ch<='9')
    25           res=res*10+ch-'0';
    26       return flag?-res:res;
    27 }
    28 int main()
    29 {
    30     int t;
    31     scanf("%d",&t);
    32     while(t--)
    33     {
    34         scanf("%d",&n);
    35         for(int i=1;i<=n;i++)
    36         {
    37             a[i]=sca();
    38             vis[i]=0;
    39             cou[i]=0;
    40         }
    41         
    42         for(int i=1;i<=n;i++)
    43         {
    44             if(vis[i]) continue;
    45             int len=1;
    46             int k=a[i];//k用来查找长度 
    47             while(k!=i)//如果当前的数与原来的位置不一样,则长度加1 
    48             {
    49                 len++;
    50                 vis[k]=1;
    51                 k=a[k];
    52             }
    53             for(int j=2;j*j<=len;j++)//这边用来计算最小公倍数,不能用lcm,因为这里是单个数 
    54             {
    55                 int c=0;
    56                 if(len%j==0)//如果可以分解质因数的话,则连续分解 
    57                 {
    58                     while(len%j==0)
    59                     {
    60                         c++;
    61                         len=len/j;
    62                     }
    63                     cou[j]=max(cou[j],c);//记录这个质因数的个数 
    64                 }
    65             }
    66             if(len>1) cou[len]=max(cou[len],1);//记住这里要加上,比如说10来分解质因数,最后剩下5(10/2=5),则cou【5】也要算进去 
    67         }
    68         
    69         ll ans=1;
    70         for(int i=2;i<=n;i++)//这边计算最小公倍数 
    71         {
    72             for(int j=0;j<cou[i];j++)
    73               ans=ans*i%MOD;
    74         }
    75         printf("%I64d
    ",ans);
    76     }
    77     return 0;
    78 }
    View Code
     
    3*2^{30}+1=32212254733230​​+1=3221225473(一个素数)的模就行了.
  • 相关阅读:
    【BZOJ2424】[HAOI2010]订货 最小费用流
    【BZOJ1935/4822】[Shoi2007]Tree 园丁的烦恼/[Cqoi2017]老C的任务 树状数组
    【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法
    【BZOJ4726】[POI2017]Sabota? 树形DP
    【BZOJ4883】[Lydsy2017年5月月赛]棋盘上的守卫 KM算法
    【BZOJ4881】5月月赛D 线段游戏 树状数组+set
    【BZOJ4518】[Sdoi2016]征途 斜率优化
    【BZOJ4818】[Sdoi2017]序列计数 DP+矩阵乘法
    【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法
    【BZOJ3211】花神游历各国 并查集+树状数组
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4733462.html
Copyright © 2020-2023  润新知