2020牛客多校第五场 Bogo Sort(置换)

2024-04-16 00:38

本文主要是介绍2020牛客多校第五场 Bogo Sort(置换),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:
置换方式为 c [ i ] = a [ b [ i ] ] c[i]=a[b[i]] c[i]=a[b[i]],a为初始数字,b为置换数组。
给你初始b数组,求存在多少个a数组经过一些置换可以变成有序数组。

思路:
第二场的时候也出了个置换题,只不过是给你初始序列和最终序列,求置换数组,而且置换方程为 c [ i ] = b [ a [ i ] ] c[i]=b[a[i]] c[i]=b[a[i]]

本题置换方式不同,但想法差不多,都得找环。而本题只是求排列 [ 1 , 2 , 3 , 4 , 5... ] [1,2,3,4,5...] [1,2,3,4,5...]可以置换成多少个其他排列,所以具体置换过程我们不考虑。

可以模拟出当 a = [ 1 , 2 , 3 , 4 , 5... ] a=[1,2,3,4,5...] a=[1,2,3,4,5...]的时候, c [ i ] = a [ b [ i ] ] c[i]=a[b[i]] c[i]=a[b[i]]置换是将 i i i置换成 b [ i ] b[i] b[i],继续往后考虑,则将置换表示成 c [ i ] = a [ b [ b [ b . . . [ b [ i ] ] ] ] c[i]=a[b[b[b...[b[i]]]] c[i]=a[b[b[b...[b[i]]]]的时候,初始的 a a a串为 a [ i ] = i a[i]=i a[i]=i,可以直接表示成 c [ i ] = b [ b [ b [ b [ b [ . . . b [ i ] ] ] ] ] c[i]=b[b[b[b[b[...b[i]]]]] c[i]=b[b[b[b[b[...b[i]]]]],所以每次置换是将 i i i置换成 b [ i ] b[i] b[i]

所以置换的方式确定了。我们要考虑的就是数目了,我们按照 i − > b [ i ] i->b[i] i>b[i]的方式找环,得到每个环的长度,当走了环长度的lcm步时,则回到原点,所以变化的路径长度为LCM(环长度),也就是所求的a数组数目


import java.math.BigInteger;
import java.util.Scanner;public class Main {static int []fa = new int[100005];static int []cnt = new int[100005];static int []array = new int[100005];BigInteger zero = BigInteger.ZERO;public static BigInteger GCD(BigInteger n,BigInteger m) {if(m.equals(BigInteger.ZERO)) {return n;}return GCD(m,n.mod(m));}public static BigInteger LCM(BigInteger n,BigInteger m) {BigInteger tmp = GCD(n,m);return n.multiply(m).divide(tmp);}public static int findset(int x) {if(x == fa[x]) {return x;}return fa[x] = findset(fa[x]);}public static void main(String args[]) {int n;Scanner cin = new Scanner(System.in);n = cin.nextInt();for(int i = 1;i <= n;i++) {fa[i] = i;cnt[i] = 0;}BigInteger ans = BigInteger.ONE;BigInteger mod = BigInteger.ONE;for(int i = 1;i <= n;i++) {array[i] = cin.nextInt();mod = mod.multiply(BigInteger.valueOf(10));}for(int i = 1;i <= n;i++) {int rx = findset(i);int ry = findset(array[i]);fa[rx] = ry;}for(int i = 1;i <= n;i++) {cnt[findset(i)]++;}BigInteger pre = BigInteger.ONE;for(int i = 1;i <= n;i++) {if(i == findset(i)) {ans = LCM(ans,BigInteger.valueOf(cnt[i]));}}System.out.println(ans.mod(mod));}
}

这篇关于2020牛客多校第五场 Bogo Sort(置换)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907365

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

stl的sort和手写快排的运行效率哪个比较高?

STL的sort必然要比你自己写的快排要快,因为你自己手写一个这么复杂的sort,那就太闲了。STL的sort是尽量让复杂度维持在O(N log N)的,因此就有了各种的Hybrid sort algorithm。 题主你提到的先quicksort到一定深度之后就转为heapsort,这种是introsort。 每种STL实现使用的算法各有不同,GNU Standard C++ Lib

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

2015多校联合训练第三场Work(hdu5326)

题意: a是b的上司,b是c的上司,则a是c的上司,问构成一个树种,有多人是 k个人的上司 思路: 先找出root,然后dfs一下就行 #include <bits/stdc++.h>#define LL long longusing namespace std;const int MAXN = 1e6;int f[105];int n, k;int mp[101][101];

2015年多校联合训练第三场RGCDQ(hdu5317)

题意: f(i)代表i数中有的素数的种数,给出区间[l,r],求区间内max(gcd(f(i))), 由于i最大是1e6,2*3*5*7*11*13*17>1e6,故最多不超过7种素数, 先打表打出1e6内的素数种数表,然后用sum[i][j]代表1-i个数中,还有j个素数的个数,最后用sum[r][j] - sum[l-1][j]求出区间内含有j个素数的数的个数,暴力找出1,2,3,4,5

2015多校联合训练第一场Tricks Device(hdu5294)

题意:给一个无向图,给起点s,终点t,求最少拆掉几条边使得s到不了t,最多拆几条边使得s能到t 思路: 先跑一边最短路,记录最短路中最短的边数,总边数-最短边数就是第二个答案 第一个答案就是在最短路里面求最小割,也就是求最大流,然后根据最短路在建个新图,权为1,跑一边网络流 模板题,以后就用这套模板了 #include <iostream>#include <cstdio>#incl

2015多校联合训练第一场Assignment(hdu5289)三种解法

题目大意:给出一个数列,问其中存在多少连续子序列,子序列的最大值-最小值< k 这题有三种解法: 1:单调队列,时间复杂度O(n) 2:RMQ+二分,时间复杂度O(nlogn) 3:RMQ+贪心,时间复杂度O(nlogn) 一:RMQ+二分 RMQ维护最大值,最小值,枚举左端点i,二分找出最远的符合的右端点j,答案就是ans += j - i+1;(手推一下就知道) 比如1 2 3