其他分享
首页 > 其他分享> > CF1673D题解

CF1673D题解

作者:互联网

题目传送门(洛谷)
题目传送门(codeforces)

题意

\(A,B,C\) 三个等差数列,给定 \(B\) 和 \(C\) 的首项、公差、项数,求有多少种可能的 \(A\)。

做法

首先,先来判断那些一定无解的情况:

  1. \(C\) 的公差不是 \(B\) 的公差的倍数;

  2. \(C\) 与 \(B\) 根本不相交;

  3. \(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