F 小苯的优雅好序列
题目需要让  数组中的每个连续子数组都是优雅的,容易看出其实我们只需要让所有长度为 
 的连续子数组优雅就可以了。
那么接下来思考如何根据给定的  和 
 求出 
 。
我们不妨设  ,题目需要求出满足要求的 
 ,即存在一个正整数 
 满足
即
也就是 
所以我们只要枚举  的因子即可。最后的 
 其实就是用所有相邻两数之差 
 的因子求出的 
 的交集,所以我们先随便求一组差的解集,然后枚举所有的 
 ,验证即可。
由于一个数  的因子数大概是 
 级别的,所以最后的时间复杂度为 
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int a[N], n;
bool check(int x) {
	for (int i = 2; i <= n; i ++ ) {
		int val = abs(a[i] - a[i - 1]);
		if (val % (x + min(a[i], a[i - 1])) != 0) return false;
	}
	return true;
}
void solve() {
	int k;
	cin >> n >> k;
	for (int i = 1; i <= n; i ++ ) cin >> a[i];
	int pos = -1;
	for (int i = 2; i <= n; i ++ ) {
		if (a[i] == a[i - 1]) continue;
		if (pos == -1 || abs(a[i] - a[i - 1]) < abs(a[pos] - a[pos - 1]))
			pos = i;
	}
	if (pos == -1) {
		cout << k << ' ' << 1ll * (1 + k) * k / 2 << endl;
		return ;
	} 
	int val = abs(a[pos] - a[pos - 1]);
	vector<int> v;
	for (int i = 1; i * i <= val; i ++ ) {
		if (val % i) continue;
		int v1 = i - min(a[pos], a[pos - 1]);
		int v2 = val / i - min(a[pos], a[pos - 1]);
		if (v1 > 0 && v1 <= k) v.push_back(v1);
		if (v2 > 0 && v2 <= k) v.push_back(v2);
	}
	sort(v.begin(), v.end());
	v.erase(unique(v.begin(), v.end()), v.end());
	int cnt = 0;
	LL sum = 0;
	for (int x : v) {
		// cout << x << ' ';
		if (check(x)) {
			cnt ++;
			sum += x;
		}
	}
	cout << cnt << ' ' << sum << endl;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
	freopen("1.out", "w", stdout);
#endif
	int T; cin >> T;
	while (T -- ) solve();
	return 0;
}

 京公网安备 11010502036488号
京公网安备 11010502036488号