比赛链接:
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;
}