Codeforces Round 919 div2 -- C -- Partitioning the Array -- 题解

目录

C -- Partitioning the Array

题目大意:

思路解析:

代码实现:


C -- Partitioning the Array

题目大意:

        给你一个长度为n的数组,你可以选择一个整数k,将数组均分为多个大小为k的子数组。如果你能找到一个整数m(m>=2),并将数组所有元素模上m,并且如果能使得子数组对应位置值相等,则得一分,问你最后这个数组总得分多少。

思路解析:

        对于某些 x 和 y ,让我们试着找出所有的 m,从而得出 x mod m == y mod m 。我们可以将等式重排为 (x-y) mod m == 0  。因此,如果 m 是 |x-y|的因数,那么 x 和 y 就等于模数 m 。

我们来求解某个 k 。如果存在某个 m,且以下条件为真,那么就存在一个有效的分割:

- a1 mod m = a1+k mod m
- a2 mod m = a2+k mod m
- ...
- an-k mod m = an mod m

如果 $ 是 |a1-a1+k|$ 的因数,则满足第一个条件  a1 mod m = a1+k mod m。如果 m 是 |a2-a2+k| 的因数,则满足第二个条件 a2 mod m = a2+k mod m 。以此类推...

因此,如果 m 是......的因数,则满足所有条件:

|a1-a_1+k|, |a2-a2+k|,...,|an-k-an|

换句话说,如果 m 是 |a1-a1+k|, |a2-a2+k|,...,|an-k-an| 的因数,则满足所有条件:

gcd(|a1-a1+k|, |a2-a2+k|,...,|an-k -an|)

因此,如果前面提到的 gcd 大于 1 ,那么对于某个 k来说,就存在一个有效的 m。

我们可以遍历所有可能的 k (记住, k是 n的整除数),并求解每个 k 以得到答案。这样做的时间复杂度为 $O((n +log n) * max divisors of n) 。请注意,每次遍历数组都需要花费 n + log n 时间,因为 gcd 在每一点上要么减半,要么保持不变。

代码实现:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        //在此输入您的代码...
        int t = in.nextInt();
        for (int o = 0; o < t; o++) {
            int n = in.nextInt();
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = in.nextInt();
            }
            long ans = 1;
            for (int i = 1; i < n; i++) {
                if (n % i != 0) continue;
                int g = 0;
                for (int j = 0; j + i < n; j++) {
                    g = gcd(g, Math.abs(arr[j + i] - arr[j]));
                }
                if (g != 1) ans ++;
            }
            System.out.println(ans);
        }
    }
    public static int gcd(int a, int b){
        if (a == 0) return b;
        if(b == 0) return a;
        return gcd(b, a % b);
    }
}

你可能感兴趣的:(算法)