比赛链接:

https://codeforces.com/contest/1673

D. Lost Arithmetic Progression

题意:

一个长度有限的等差序列 \(A\),和一个长度有限的等差序列 \(B\),取它们的公共子集为 \(C\),现在已知 \(B\) 的首项、公差、序列长度分别为 \(b、q、y\)\(C\) 的首项、公差、序列长度分别为 \(c、r、z\),问 \(A\) 有多少种可能,若有无限种,输出 - 1。

思路:

首先找出 0 的可能,当 \(B\) 的首项大于 \(C\) 的首项或者 \(B\) 的尾项小于 \(C\) 的尾项,为 0。
\(B\) 的公差要能整除 \(C\) 的公差,同时,\(C\) 的首项要是 \(B\) 中的某一项,即 \((c - b) % q == 0\),否则,为 0。
接着看 - 1 的情况,\(A\) 可能是 \(C\) 的一个扩充,当 \(b > c - r\) 的时候,可以向左边无限扩充,同理,当 \(B\) 的尾项小于 \(C\) 的尾项 + \(r\) 时,可以向右边无限扩充。
除去上述情况,序列都是有限的。
\(A\) 的公差为 \(p\),那么显然 \(lcm(p, q) = r\),所以可以枚举每一个 \(r\) 的因数,对于每一个因数,它对答案的贡献就是 \(\frac{r}{q} * \frac{r}{q}\),因为以这个数为公差的序列可以向两边分别扩张 \(\frac{r}{q} - 1\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 1e9 + 7;
LL gcd(LL a, LL b){
	return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b){
	return a * b / gcd(a, b);
}
void solve(){
	LL b, q, y, c, r, z;
	cin >> b >> q >> y;
	cin >> c >> r >> z;
	if ( c < b || c + r * (z - 1) > b + q * (y - 1) ){
		cout << "0\n";
		return;
	}
	if ( r % q || (c - b) % q ){
		cout << "0\n";
		return;
	}
	if ( b > c - r || b + q * (y - 1) < c + r * z ){
		cout << "-1\n";
		return;
	}
	LL ans = 0;
	for (LL p = 1; p * p <= r; p ++ ){
		if (r % p == 0){
			if (lcm(p, q) == r){
				ans = (ans + (r / p) * (r / p) % mod) % mod;
			}
			if (p * p != r && lcm(r / p, q) == r){
				ans = (ans + p * p) % mod;
			}
		}
	}
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T;
	cin >> T;
	while (T -- )
		solve();
	return 0;
}
posted on 2022-06-18 17:31  Hamine  阅读(14)  评论(0编辑  收藏  举报