Codeforces Round #785 (Div. 2) - D. Lost Arithmetic Progression

GCD

Problem - D - Codeforces

题意

有 2 个等差数列 A,B,它们公有的项组成新的等差数列 C;

现在给出 B 的(首项,公差,项数)= (b,q,y),C 的(首项,公差,项数)= (c,r,z)

求满足条件的 A 的数量,如果有无穷多个输出 -1

思路

记 A,B,C 的首项,公差,末项分别为 \(l[0/1/2],d[0/1/2],r[0/1/2]\)

  1. 首先要明确 \(lcm(d[0],d[1])=d[2]\)

  2. 先排除 B,C 就不满足条件的情况

    1. B 一定要完全覆盖 C,因此当 \(l[1]>l[2]\;or\;r[1]<r[2]\;or\;d[1]\nmid d[2]\) 时,不满足 C 是 B 的某些项,此时 A 无论是什么都没用,输出 0

    2. B 与 C 在 \(d[1]\) 意义 下要是对齐的,因此

      ll x = (l[1] % d[1] + d[1]) % d[1];
      ll y = (l[2] % d[1] + d[1]) % d[1];
      if (x != y)
      	return 0;
      
  3. 至此 B,C 已经协调了,再找 A 的数量 (画个图会很好理解)

    1. 如果两端中至少有一端,B 比 C 延长的长度小于 \(d[2]\), 则 A 在这一段即使无限长也可以,输出 -1
    2. 反之,如果两端 B 比 C 延长的长度都 >= \(d[2]\) 则 A 在任何一端最多延长 \(d[2]-1\), 此时枚举 \(d[2]\) 的因子 \(g\),如果满足\(lcm(g,d[1])=d[2]\), 则当前的 \(g\) 可以作为 \(d[0]\), 那 A 在任何一端有 \(0,1,...\frac {d[2]-1}g\) 种可能,因为 \(g\mid d[2]\), 所以当前的 \(g\) 对答案的贡献就是 \((\frac {d[2]}g)^2\)

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>

using namespace std;
#define endl "\n"

typedef long long ll;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
ll l[3], r[3], d[3], c[3];

void add(ll &a, ll b)
{
	a += b;
	if (a >= mod)
		a -= mod;
}
ll gcd(ll a, ll b)
{
	if (b == 0)
		return a;
	return gcd(b, a % b);
}
ll lcm(ll a, ll b)
{
	return a / gcd(a, b) * b;
}

ll calc(ll g)
{
	return (d[2] / g) * (d[2] / g) % mod;
}
ll solve()
{
	r[1] = l[1] + d[1] * (c[1] - 1);
	r[2] = l[2] + d[2] * (c[2] - 1);
	if (l[1] > l[2] || r[1] < r[2] || d[2] % d[1] != 0)
		return 0;
	ll x = (l[1] % d[1] + d[1]) % d[1];
	ll y = (l[2] % d[1] + d[1]) % d[1];
	if (x != y)
		return 0;
	if (l[2] - l[1] < d[2] || r[1] - r[2] < d[2])
		return -1;
	ll ans = 0;
	for (int i = 1; i <= d[2] / i; i++)
	{
		if (d[2] % i)
			continue;
		ll p = i, q = d[2] / p;
		if (lcm(p, d[1]) == d[2])
			add(ans, calc(p));
		if (p != q && lcm(q, d[1]) == d[2])
			add(ans, calc(q));
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while(T--)
	{
		cin >> l[1] >> d[1] >> c[1];
		cin >> l[2] >> d[2] >> c[2];
		cout << solve() << endl;
	}
    return 0;
}
posted @ 2022-10-05 11:27  hzy0227  阅读(15)  评论(0编辑  收藏  举报