Strange Fractions[2021 ICPC 上海站 D]&U207965 Strange Fractions 增强版
参考(全题解)
题目链接中,增强版 T 增加到了 1e6,并要求 a,b 互质,ban掉了第一种做法(赛版不要求 a,b 互质);
题目大意
给定一个正分数 qp,我们需要找到两个正整数 a,b 满足 qp=ba+ab ,如果不存在,则输出 0,0 ;
( 1≤T≤105,1≤p,q≤107 ,要求 1≤a,b≤109 )
试差
思路
在 p,q 化为最简后,等价于寻找 a,b 满足 aba2+b2=qp ,我们只需要预处理出所有小于 1e7 的平方数,依次匹配~
时间复杂度 O(Tp) ;
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <bits/stdc++.h> using namespace std; typedef long long ll; int twi[10004]; int tti[10000007]; int main() { int t,p,q; for(int i=1;i*i<=10000000;i++) { twi[i]=i*i; tti[i*i]=i; } cin>>t; while(t--) { scanf("%d%d",&p,&q); if (p < 2 * q) { printf("0 0\n"); continue; } int g=__gcd(p,q); p/=g,q/=g; int f=0; for(int i=1;twi[i]<=p&&!f;i++) { int lst=tti[p-twi[i]]; if(lst&&i*lst==q) { printf("%d %d\n",min(i,lst),max(i,lst)); f=1; } } if(!f)printf("0 0\n"); } }
|
二进制枚举
思路
我们可以证明 a,b 互质时 gcd(a2+b2,ab)=1 成立, qp化简后,我们便可以处理出 p 的所有互质因子对 a,b ,并验证与 q 的关系;
至于为什么要求是互质因子对,可以简化枚举过程和省略枚举后的约分,由于质因子最多8个(2⋅3⋅5⋅7⋯19),所以时间复杂度 O(T28) ;
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll N = 1e7; int pri[N + 7], c = 0, mrk[N + 7]; bool n[N + 7]; void prime() { n[0] = n[1] = 1; for (int i = 2; i <= N; i++) { if (!n[i]) pri[c++] = i, mrk[i] = i; for (int j = 0; j < c && i * pri[j] <= N; j++) { n[i * pri[j]] = 1; mrk[pri[j] * i] = pri[j]; if (i % pri[j] == 0) { mrk[pri[j] * i] *= mrk[i]; break; } } } } int v[10]; void solve() { int tot = 0, f = 0, a, b, p, q; scanf("%d%d", &p, &q); if (p < 2 * q) { printf("0 0\n"); return; } int g = __gcd(p, q); p /= g, q /= g; tot = 0, f = 0; while (q != 1) { v[tot++] = mrk[q]; q /= mrk[q]; } 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) { printf("%d %d\n", min(a, b), max(a, b)); return; } } printf("0 0\n"); return; } int main() { int t; prime(); cin >> t; while (t--) { solve(); } }
|
求根公式
思路
不妨设 ba=x ,那么有 qp=x+x1 ,问题转化为求 qx2−px+q=0 的有理根;
由于求根公式 x=2qp+p2−4q2 ,在判断根式有理后,即可获得分子分母;
时间复杂度 O(Tlogp) ;
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { ll t,p,q; cin>>t; while(t--) { scanf("%lld%lld",&p,&q); if (p < 2 * q) { printf("0 0\n"); continue; } ll g=__gcd(p,q); p/=g,q/=g; ll s=(ll)sqrt(p*p-4*q*q); if(s>=0&&s*s==p*p-4*q*q) { ll fz=p+s,fm=2*q; ll gtmp=__gcd(fz,fm); fz/=gtmp,fm/=gtmp; printf("%lld %lld\n",min(fz,fm),max(fz,fm)); } else printf("0 0\n"); } }
|
ED
\