Strange Fractions
题意
在规定的范围内求解整数 a , b 满足
思路
这个题目让我来做的话,可能就暴毙了。
首先我们来看几个对这个题目而言很重要的性质。
-
假设互质,那么原来的输入总可以考虑为 。 总可以证明成功。
-
假设互质,如果 。那么原来的式子便可以化简为 ,因此 互质。
-
。
假设
那么可以分为以下两种情况
-
-
, 假设 与 那么 。
因此可以证得 由于 所以 ,同理 。
-
那么因此,我们就可以得到 和
我们有两种做法
-
我们注意到 而 约为 我们,通过枚举因子 得到我们的答案,那么复杂度就为 。 大概为 可过
-
同样的,我们发现, 最多有 个素因子,因此,我们通过二进制枚举这些数的分配情况大概为 ,最终,我们也可以得到我们的答案。同上面的情况相同,如果我们想要知道素因子的个数最多需要 次枚举。因此复杂度同上。
如果我们想要更快的话,我们可以通过欧拉筛,每次得到最小素因子和最小素因子的k次方的形式快速得到答案,以降低时间复杂度。
#include <iostream>
#include <numeric>
using namespace std;
const int N = 1e7 + 10;
bool is[N];
int prime[N];
int mk[N];
void table() {
int tot = 0;
for (int i = 2 ; i < N ; i ++ ) {
if(!is[i]) {
prime[tot++] = i;
mk[i] = i;
}
for (int j = 0 ; j < tot &&
1ll * i * prime[j] < N;
j ++ ) {
is[i * prime[j]] = 1;
if(i % prime[j]) {
mk[prime[j] * i] = prime[j];
} else {
mk[prime[j] * i] = prime[j] * mk[i];
break;
}
}
}
}
int v[10];
void solve() {
int p , q ; cin >> p >> q;
if (p < 2 * q) {
cout << "0 0\n";
return ;
}
int g = gcd(p , q);
p /= g , q /= g;
int tot = 0;
while(q != 1) v[tot ++ ] = mk[q] , q /= mk[q];
int a , b;
for (int i = 0 ; i < (1 << tot) ; i ++ ) {
a = 1 , b = 1;
for (int j = 0 ; j != tot ; j ++ ) {
if((i >> j) & 1) a *= v[j];
else b *= v[j];
}
if(a * a + b * b == p) {
if(a > b) swap(a , b);
cout << a << ' ' << b << '\n';
return ;
}
}
cout << "0 0\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t ; cin >> t;
table();
while(t--) solve();
}
或者
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void solve() {
int p , q ; cin >> p >> q;
if (p < 2 * q) {
cout << "0 0\n";
return ;
}
int g = gcd(p , q);
p /= g , q /= g;
int a = 1 , b = 1;
vector<int> v;
for (int i = 2 ; i * i <= q ; i ++ ) {
if(q % i == 0) {
int kki = 1;
while(q % i == 0) {
kki *= i;
q /= i;
}
v.push_back(kki);
}
}
if(q > 1) v.push_back(q);
for (int i = 0 ; i < (1 << v.size()) ; i ++ ) {
a = 1 , b = 1;
for (int j = 0 ; j != v.size() ; j ++ ) {
if((i >> j) & 1) a *= v[j];
else b *= v[j];
}
if(a * a + b * b == p) {
if(a > b) swap(a , b);
cout << a << ' ' << b << '\n';
return ;
}
}
cout << "0 0\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t ; cin >> t;
while(t--) solve();
return 0;
}