1. 问题描述:
有一个长度为 k 的整数数组 x0,x1,…,xk−1。不幸的是,这个数组已经丢失了,我们甚至不知道 k 的具体值。幸运的是,我们找到了另一个利用数组 x 生成的长度为 n + 1 的数组 a0,a1,…,an。数组 a 的正式描述如下:
- a0 = 0。
- 对于 1 ≤ i ≤ n,ai = x(i−1) mod k + ai−1;
例如,当 x=[1,2,3] 并且 n = 5 时,生成数组 a 的过程如下:
a0 = 0
a1 = x0 mod 3 + a0 = x0 + 0 = 1
a2 = x1 mod 3 + a1 = x1 + 1 = 3
a3 = x2 mod 3 + a2 = x2 + 3 = 6
a4 = x3 mod 3 + a3 = x0 + 6 = 7
a5 = x4 mod 3 + a4 = x1 + 7 = 9
所以,当 x = [1,2,3] 并且 n = 5 时,可以生成数组 a = [0,1,3,6,7,9];
现在,我们希望你通过数组 a 找回数组 x,更具体地说,已知 1 ≤ k ≤ n,请你找到所有可能的 k 值,即数组 x 的所有可能长度。
输入格式
第一行包含整数 n。第二行包含 n 个整数 a1,a2,…,an。注意,由于 a0 一定等于 0,所以在输入中并未给出。
输出格式
第一行输出一个整数 l,表示数组 x 的所有可能长度的数量。第二行按升序输出 l 个整数,表示数组 x 的所有可能长度。
数据范围
前四个测试点满足 1 ≤ n ≤ 5,所以测试点满足 1 ≤ n ≤ 1000,1 ≤ ai ≤ 10 ^ 6。
输入样例1:
5
1 2 3 4 5
输出样例1:
5
1 2 3 4 5
输入样例2:
5
1 3 5 6 8
输出样例2:
2
3 5
输入样例3:
3
1 5 3
输出样例3:
1
3
来源:https://www.acwing.com/problem/content/description/4404/
2. 思路分析:
分析题目可以知道这道题目类似于差分的题目,由于 n 最大是 1000,所以需要将时间复杂度控制在 O(n ^ 2) 以内,由于是 O(n ^ 2)所以我们可以考虑枚举 k,判断当前的 k 是否合法即可,所以问题的关键是如何判断当前的 k 是否合法,可以找一下规律,由下图可以知道我们可以判断当前这一组与上一组对应位置的值是否相等即可,不相等说明不匹配,枚举的过程中记录下合法的 k 即可
3. 代码如下:
python:
class Solution:
def process(self):
n = int(input())
a = [0] + list(map(int, input().split()))
res = list()
for k in range(1, n + 1):
is_match = 1
for i in range(k + 1, n + 1):
# 判断当前这一组与上一组的对应位置是否相等不相等一定不合法
if a[i] - a[i - 1] != a[i - k] - a[i - k - 1]:
is_match = 0
break
if is_match:
res.append(k)
print(len(res))
print(*res)
if __name__ == '__main__':
Solution().process()
go:
package main
import "fmt"
func main() {
var n int
fmt.Scan(&n)
a := make([]int, n+10)
for i := 1; i <= n; i++ {
fmt.Scan(&a[i])
}
var res []int
for k := 1; k <= n; k++ {
is_match := 1
for i := k + 1; i <= n; i++ {
if a[i]-a[i-1] != a[i-k]-a[i-k-1] {
is_match = 0
break
}
}
if is_match == 1 {
res = append(res, k)
}
}
fmt.Println(len(res))
for i := 0; i < len(res); i++{
fmt.Print(res[i], " ")
}
}