Educational Codeforces Round 106 (Rated for Div. 2) D. The Number of Pairs
题意
给定三个正整数(c,d,x),询问有多少对正整数对((a,b)),满足
限制
(1le Tle 10^4)
(1le c,d,xle 10^7)
思路
对于原式
由(gcd)及(lcm)的数学性质,很容易得到一个结论:(lcm)定是(gcd)的倍数。
那么便能将上式化为
右侧定是一个整数,即(x+dcdot gcd)定是(c)的倍数
那么我们可以(O(sqrt x))枚举(x)的所有因子作为(gcd)
由于(c,d,x)已知,在满足上述条件的前提下,可通过(gcd,c,d,x)直接计算出所匹配的(lcm)
问题现在便转化成了“在已知(gcd)与(lcm)的前提下求有多少对整数对满足条件”
从数学角度可知
(gcd(a,b))是(a,b)的质因子的交集
(lcm(a,b))是(a,b)的质因子的并集
那么(frac{lcm}{gcd})便是多出来的质因子的乘积
对于(frac{lcm}{gcd})的每种质因子,不论数量,都应该全数位于(frac{a}{gcd})或者全数位于(frac{b}{gcd})中
否则,这些质因子在(a)与(b)中同时出现,便会算在(gcd)中,于此时情况不符
所以如果我们想要构造(a,b)两个数,每种质因子只能够挑其中一个数乘进去
设(frac{lcm}{gcd})的质因子种类数为(n),则能够构造出的整数对共有(2^n)种
实践可得,在线的质因子分解算法都将会完美地TLE 15
所以考虑离线处理每个数拥有的质因子种类数
写法类似于埃氏素数筛法,详情见代码部分的(init)函数
注意(frac{frac{x}{gcd}+d}{c})的数据范围最大可能达到(2cdot 10^7)
代码
(1075ms/2000ms)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2e7;
int r[MAXN+50]; //记录每个数字的质因子种类数
void init()
{
for(int i=2;i<=MAXN;i++)
if(!r[i]) //判断i是否为素数
{
for(int j=i;j<=MAXN;j+=i)
r[j]++; //i在范围内的倍数的质因子种类数++
}
}
ll c,d,x,ans;
void add(int gcd)
{
ll lcm=x+d*gcd;
if(lcm%c==0)
{
lcm/=c;
if(lcm%gcd==0)
ans+=1LL<<r[lcm/gcd];
}
}
void solve()
{
ans=0;
cin>>c>>d>>x;
int s=sqrt(x);
for(int i=1;i<=s;i++)
{
if(x%i==0) //枚举x的因子i
{
add(i);
if(i*i!=x)
add(x/i);
}
}
cout<<ans<<'
';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
init();
int T;cin>>T;while(T--)
solve();
return 0;
}