CF1673D题解
作者:互联网
题意
\(A,B,C\) 三个等差数列,给定 \(B\) 和 \(C\) 的首项、公差、项数,求有多少种可能的 \(A\)。
做法
首先,先来判断那些一定无解的情况:
-
\(C\) 的公差不是 \(B\) 的公差的倍数;
-
\(C\) 与 \(B\) 根本不相交;
-
\(C\) 中元素 \(B\) 中没有——即 \(C\) 的边界比 \(B\) 的边界远
这三种情况容易证明都一定没有解,之后要考虑无穷解:当 A 的某一端可以无限延伸,就是无穷。
对于判定无穷解,本蒟蒻提供一种做法:把 \(C\) 的左右端点各扩展一个数,如果这两个数有一个数不在 \(B\) 的值域范围内,就代表 \(A\) 无穷解,因为这样 \(A\) 可以无限延伸。
最后是判断解的数量,容易证明,\(A\) 的公差一定是 \(C\) 的公差的约数,这样就可以枚举 \(C\) 的约数,判断它与 \(B\) 是否有其他交点,如果没有就统计答案。
判断是否有其他交点:设此时 \(A\) 的公差为 \(d_A\),B 的公差为 \(d_B\),\(C\) 的公差为 \(d_C\),若 \(\gcd(d_C/d_A,d_C/d_B)=1\) 则没有其他交点。
证明:可以把上边的做法想象成:把长度为 \(d_C\) 的线段分成每段长度都是 \(d_A\) 的若干段,对 \(B\) 同理,这样分割点就是序列中的数,如果段数的最大公约数是 \(1\),就代表中间没有分割点相交,也就是没有其他相等的数。
统计答案的个数:多端点有 \(d_C/d_A\) 种情况,右端点同理,平方就好了。
代码
// Problem: D. Lost Arithmetic Progression
// Contest: Codeforces - Codeforces Round #785 (Div. 2)
// URL: https://codeforces.com/problemset/problem/1673/D
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define mod 1000000007
#define int long long
#define db double
#define eps (1e-11)
using namespace std;
namespace Std {
template <typename tp>
void read(tp &x) {
x = 0;
tp nev = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') nev = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
x *= nev;
}
template <typename tp>
void write(tp x) {
if (x < 0) {
putchar('-');
write(-x);
return;
}
if (x / 10) write(x / 10);
putchar((x % 10) ^ 48);
}
int n, a1, b1, c1, a2, b2, c2;
int gcd(int x, int y) { return (!y) ? x : gcd(y, x % y); }
int main() {
read(n);
while (n--) {
read(a1);
read(b1);
read(c1);
read(a2);
read(b2);
read(c2);
if (b2 % b1 != 0 || a2 < a1 || a1 + b1 * (c1 - 1) < a2 + b2 * (c2 - 1) ||
(a2 - a1) % b1 != 0) //无解
{
puts("0");
continue;
}
if (a1 + b1 * (c1 - 1) - a2 - b2 * (c2 - 1) < b2 || a2 - a1 < b2) //无穷解
{
puts("-1");
continue;
}
int ans = 0;
for (int i = 1; i * i <= b2; ++i) {
if (b2 % i == 0) {
int j = b2 / i;
if (gcd(b2 / b1, j) == 1) {
ans += j * j;
ans %= mod;
}
if (gcd(b2 / b1, i) == 1) {
ans += i * i;
ans %= mod;
}
if (j == i && gcd(b2 / b1, i) == 1) {
ans -= i * i;
ans %= mod;
ans += mod;
ans %= mod;
}
}
}
printf("%lld\n", ans);
}
return 0;
}
} // namespace Std
#undef int
int main() { return Std::main(); }
标签:CF1673D,int,题解,a1,read,a2,b2,公差 来源: https://www.cnblogs.com/lncyz/p/16250862.html