【CF1499D】The Number of Pairs

题目

题目链接:https://codeforces.com/contest/1499/problem/D
给定 \(c,d,x\),求有多少二元组 \((a,b)\) 满足

\[c\times \text{lcm}(a,b)-d\times \gcd(a,b)=x \]

\(Q\leq 10^4;1\leq c,d,x\leq 10^7\)

思路

因为 \(\text{lcm}(a,b)\) 一定是 \(\gcd(a,b)\) 的倍数,所以等号左边一定是 \(\gcd(a,b)\) 的倍数,那么 \(\gcd(a,b)\) 必然是 \(x\) 的因子。
那么枚举 \(x\) 的所有因子 \(i\),就可以得到对应的 \(\gcd(a,b)=i,\text{lcm}(a,b)=\frac{x+di}{c}\)
\(a=\gcd(a,b)\times p_1^{a_1}\times p_2^{a_2}\times \cdots,b=\gcd(a,b)\times q_1^{b_1}\times q_2^{b_2}\times \cdots\),那么 \(\text{lcm}(a,b)=\gcd(a,b)\times p_1^{a_1}\times p_2^{a_2}\times \cdots\times q_1^{b_1}\times q_2^{b_2}\cdots\)
也就是对于 \(k=\frac{\text{lcm}(a,b)}{\gcd(a,b)}\) 的每一个质因子,我们分配到 \(a\) 中或者 \(b\) 中都是一种合法方案。记 \(x\) 的止因子数量为 \(f(x)\),那么方案数就是 \(2^{f(k)}\)
那么直接预处理出 \(1\sim 2\times 10^7\) 所有数的最大质因子,然后就可以预处理出 \(f(x)\) 了。
时间复杂度 \(O(n\log \log n+Q\sqrt{x})\),其中 \(n=\max(c,d)\leq 10^7\)

代码

VP 的时候数组一开始只开到了 \(10^7\) 调了半天。。。

#include <bits/stdc++.h>
#define mp make_pair
#define ST first
#define ND second
using namespace std;
typedef long long ll;
typedef long double ld;

const int N=20000010;
int Q,m,c,d,x,prm[N],f[N],v[N];
ll ans;
bool vis[N];

void findprm(int n)
{
	for (int i=2;i<=n;i++)
	{
		if (!vis[i]) prm[++m]=i;
		for (int j=1;j<=m;j++)
		{
			if (n/prm[j]<i) break;
			vis[i*prm[j]]=1;
		}
	}
	for (int i=1;i<=m;i++)
		for (int j=prm[i];j<=n;j+=prm[i])
			v[j]=prm[i];
}

void calc(ll g)
{
	ll l=x+g*d;
	if (l%(1LL*c)) return;
	l=l/(1LL*c);
	if (l%g) return;
	ans=ans+(1LL<<f[l/g]);
}

signed main()
{
	findprm(N-1);
	for (int i=2;i<N;i++)
	{
		int p=i;
		while (!(p%v[i])) p/=v[i];
		f[i]=f[p]+1;
	}
	scanf("%d",&Q);
	while (Q--)
	{
		scanf("%d%d%d",&c,&d,&x);
		ans=0;
		for (int i=1;i*i<=x;i++)
			if (!(x%i))
			{
				calc(i);
				if (i*i!=x) calc(x/i);
			}
		cout<<ans<<endl;
	}
	return 0;
}

posted @ 2021-04-29 11:57  stoorz  阅读(69)  评论(0编辑  收藏  举报