Practice.
A. Everybody Likes Good Arrays!
题意
给定一个数组 \(a\),定义一次操作为将奇偶性相同的相邻元素相乘并合并为一个元素,输出让数组 \(a\) 满足所有相邻数奇偶性不同的最小操作数量。
思路
显然,奇偶性相同的两个数相乘后奇偶性是不变的,那么我们只需统计有多少组相邻元素的奇偶性相同即可。
时间复杂度:\(O(n)\)
对应AC代码
import java.math.BigInteger;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while(t -- > 0){
int n = scanner.nextInt();
int cur = scanner.nextInt() % 2;
int cnt = 0;
for(int i=1;i<n;i++){
int a = scanner.nextInt();
if(a % 2 == cur) cnt ++;
else cur = a % 2;
}
System.out.println(cnt);
}
}
}
还是挺简单的思维题
B. Emordnilap
题意
给定一个整数 \(n\),对于所有 \(n\) 的排列,分别将各个排列镜像复制到右边,输出所有新数对的逆序对的总数量。
思路
可以证明,对于任意一个排列,所有大于 \(1\) 的数字 \(t\) 总能在其右边找到总共为 \(2 \times (t-1)\) 个比它小的数,从而构成对应数量的逆序对。因而,对于一个长度为 \(n\) 的排列,进行镜像复制后,逆序对总数为 \(2 \times (1+2+...+(n-1))=n \times (n-1)\)。
显然,对于 \(n\),总共有 \(A_n^n\) 种排列,与上式相乘即可。
时间复杂度:\(O(n)\)
对应AC代码
import java.math.BigInteger;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while(t -- > 0){
long n = scanner.nextInt();
long fact = 1L, mod = 1000000007;
for(long i=2;i<=n;i++) fact = (fact * (i % mod)) % mod;
System.out.println((((fact * (n % mod)) % mod) * ((n - 1) % mod)) % mod);
}
}
}
难得B题想的这么快
C. Quiz Master
题意
给定数组 \(a\),选择任意可不连续的子序列 \(b\),满足对于任意 \(t \in [1,m]\),有 \(b_i \bmod t = 0\),输出满足条件的子序列中 \(b_{\max}-b_{\min}\) 的最小值。
思路
双指针,类似于滑动窗口的解法。
我们考虑用双指针维护一个 \([l,r]\) 的满足题意的区间,在向右移动 \(r\) 的同时,找出满足条件的 \(l\) 的最小值即可。
更具体地说,我们可以开一个数组 \(cnt\) ,在向右移动 \(r\) 之前,我们先将 \(a[r]\) 的所有因子 \(f[a[r]]\) 对应的 \(cnt[f[a[r]]] +1\),并在加之前判断值是否为 \(0\),如果是,那么这个因数是第一次出现,因此即可统计 \([1,m]\) 是否被完全覆盖。向右移动 \(l\) 之前的操作与上述操作类似。
时间复杂度:\(O(n \times f(x)),f(x)为x的因数数量\)
对应AC代码
import java.math.BigInteger;
import java.util.*;
public class Main{
static int N = 100010;
private static List<List<Integer>> init(){
List<List<Integer>> res = new ArrayList<>();
for(int i=0;i<=N;i++) res.add(new ArrayList<>());
for(int i=1;i<=N;i++)
for(int j=i;j<=N;j+=i){
res.get(j).add(i);
}
return res;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<List<Integer>> f = init();
int t = scanner.nextInt();
nxt:
while(t -- > 0){
int n = scanner.nextInt(), m = scanner.nextInt();
int[] a = new int[n];
for(int i=0;i<n;i++) a[i] = scanner.nextInt();
Arrays.sort(a);
int l = 0, r = 0, best = Integer.MAX_VALUE, now = 0;
int[] cnt = new int[N];
while(r < n){
for(int each : f.get(a[r])){
if(each > m) break;
if(cnt[each] == 0) now ++;
cnt[each] ++;
}
while(now == m){
best = Math.min(a[r] - a[l], best);
for(int each : f.get(a[l])){
if(each > m) break;
if(cnt[each] == 1) now --;
cnt[each] --;
}
l ++;
}
r ++;
}
System.out.println(best == Integer.MAX_VALUE ? -1 : best);
}
}
}
妙啊.jpg