T组测试数据,每次给出a,b,c,d。gcd(a,x)=b,lcm(c,x)=d。求满足条件的x的个数。
由题意可知,x是d的约数。
所以暴力的方法就是:
枚举d的所有约数,然后判断一下条件是否成立(即gcd(a,x)==b && c*x/gcd(c,x)==d)
暴力求所有约数的方法:
O
(
N
)
O(\sqrt N)
O(N)。其中N可以取到
2
∗
1
0
9
2 * 10^9
2∗109
时间复杂度:
O
(
T
∗
N
)
)
O(T * \sqrt N ))
O(T∗N)) 会超时。
本题的时间复杂度瓶颈在求d的所有约数上面。

思路参考:https://www.acwing.com/solution/content/3101/
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 50010;
struct fact{
int p, s;
}factor[N];//将d分解质因数
int fcnt;
int T;//t组测试数据
int dividor[1601], dcnt;//存储d的所有约数
int primes[N], cnt;
bool st[N];
//线性筛
void init(int n)
{
for(int i = 2; i <= n; i ++)
{
if(!st[i]) primes[cnt ++] = i;
for(int j = 0; i * primes[j] <= n; j ++)
{
st[i * primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
}
//暴搜d的所有约数
void dfs(int u, int p)
{ //如果考虑完所有的质数之后
if(u == fcnt)
{
dividor[dcnt ++] = p;
return;
}
for(int i = 0; i <= factor[u].s; i ++)
{
dfs(u + 1, p);
p *= factor[u].p;
}
}
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
init(N);
cin >> T;
while(T --)
{
int a, b, c, d;
scanf("%d%d%d%d",&a,&b,&c,&d);
//将d分解质因数 此时的复杂的不是O(根号N) 而是n/ln(n)
//这里不是从2开始枚举到根号n 而是枚举1~根号N的每一个质数。所以时间复杂度取决与质数个数也就是
//n/(ln n)
fcnt = 0;//统计质因子的数量
int t = d;
for(int i = 0; primes[i] <= t / primes[i]; i ++)
{
int p = primes[i];
if(t % p == 0)
{
int s = 0;
while(t % p == 0) s ++, t /= p;
factor[fcnt ++] = {p, s};
}
}
//如果t大于1的话 说明是最后一个质因数。
if(t > 1) factor[fcnt ++] = {t, 1};
dcnt = 0;
dfs(0, 1);//第几个质数,p存储答案
int res = 0;
for(int i = 0; i < dcnt; i ++)
{
int x = dividor[i];
if(gcd(a, x) == b && (LL)c * x / gcd(c, x) == d) res ++;
}
cout << res << endl;
}
return 0;
}
本题最为核心的地方,在于时间复杂度的分析。