题目链接:点击打开链接
题意:给定n,求1/x + 1/y = 1/n (x<=y)的解数。(x、y、n均为正整数)
题解:首先看一下最直观的思路。两层for循环去暴力去找x和y。然后用个ans来统计。时间复杂度太高。会时间超限。
那么就去考虑有没有什么优化。
然后我们发现除了去变形这个式子就没有其他方法了。
1/x+1/y=1/n
--> 两边乘上xyn,这一步很容易想到。
nx+ny=xy
--> 因为x,y,n为正整数,所以n > y >= x ,一定存在x = n-a,y = n - b。带入式子化简。这一步能想到简直是玄学!!
b*a=n*n。
观察式子。我们很容易看出来,a和b是n*n的两个因子且a>b。那么问题就变成了。n*n的因子的所有的组合方式了。
那么问题了。如何求某个数的因子。
那么约数定理出现了:
n可以
分解质因数:n=p1^a1×p2^a2×p3^a3*…*pk^ak,
由约数定义可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1 ,共(a1+1)个;同理p2^a2的
约数有(a2+1)个......pk^ak的约数有(ak+1)个。
故根据
乘法原理:n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)。
然后就代码如下:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int num[64];
int main(){
int cases , t = 0;
scanf("%d",&cases);
while(cases--){
int n,p = 0;
memset(num,0,sizeof(num)); // num数组类似桶排序。只存某个质因子出现了几次。不存具体数
cin >> n;
for(int i = 2 ; i * i<= n ; i++){ // 解释一下为什么为什么要 i*i <= n . 能过滤很多没用的因素
if(n %i == 0){
while(n%i == 0){
num[p]++;
n /= i;
}
p++;
}
}
if(n != 1){ // 若n为质数。那么他除了自己的没有其他质因子。
num[p]++;
p ++;
}
for(int i = 0 ; i < p ; i ++) // 每个因子乘二原因是。我们算的n的因子而不是n方的。n方的质因子的种类和n一样但是个数比n多一倍
num[i] *= 2;
int ans = 1;
for(int i = 0 ; i < p ; i ++)
ans *= (num[i] + 1);
cout << (ans + 1)/2 << endl; // +1 的原因是消除奇数和偶数的影响。 除2是因为 x < y有重复的。
}
}