目录
? ? ? ? 给你一个长度为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);
}
}