原题题面
有T个输入。
每组输入给出两个正整数
a
,
b
(
a
,
b
≤
2
×
1
0
6
)
a,b(a,b\leq 2 × 10^6)
a,b(a,b≤2×106)。
请找到四个正整数
c
,
d
,
e
,
f
(
f
<
b
,
d
<
b
,
1
≤
c
,
e
≤
4
×
1
0
12
)
c,d,e,f(f<b,d<b,1\leq c,e \leq 4× 10^{12})
c,d,e,f(f<b,d<b,1≤c,e≤4×1012),使他们满足:
c
d
−
e
f
=
a
b
\frac{c}{d}-\frac{e}{f}=\frac{a}{b}
dc−fe=ba
如果有多组数据,输出其中一组。如果不存在,输出“-1 -1 -1 -1”。
输入样例
3
4 1
1 6
37 111
输出样例
-1 -1 -1 -1
1 2 1 3
145 87 104 78
题面分析
首先显然,当
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)不为1时,我们可以令
a
′
=
a
g
c
d
(
a
,
b
)
,
b
′
=
b
g
c
d
(
a
,
b
)
a'=\frac{a}{gcd(a,b)},b'=\frac{b}{gcd(a,b)}
a′=gcd(a,b)a,b′=gcd(a,b)b。构造
a
′
+
1
b
′
−
1
b
′
=
a
b
\frac{a'+1}{b'}-\frac{1}{b'}=\frac{a}{b}
b′a′+1−b′1=ba
所以输出"a’+1 b’ 1 b’"即可。
当
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1时,易知
c
d
−
e
f
=
c
f
−
d
e
d
f
\frac{c}{d}-\frac{e}{f}=\frac{cf-de}{df}
dc−fe=dfcf−de
即
d
f
=
k
b
df=kb
df=kb(k为正整数)
首先我们可以证明一下结论:
结论①:
b
b
b不能是质数或1。
证明:
b不能是1显然。
假设
b
b
b是质数,那
b
b
b的因子只有
1
,
b
1,b
1,b,即
d
,
f
d,f
d,f只能分别取1和b的倍数,这与
d
<
b
,
f
<
b
d<b,f<b
d<b,f<b矛盾。故①得证。
结论②:
b
b
b不能是质数幂(即
p
k
p^k
pk)
证明:
假设
b
=
p
k
b=p^k
b=pk,设
d
=
p
a
d=p^a
d=pa,则
f
=
p
k
−
a
f=p^{k-a}
f=pk−a,由扩展欧几里得得知
c
f
−
d
e
=
a
cf-de=a
cf−de=a有正整数解的充要条件是
g
c
d
(
d
,
f
)
∣
a
gcd(d,f)|a
gcd(d,f)∣a故
g
c
d
(
d
,
f
)
=
p
m
i
n
{
a
,
k
−
a
}
gcd(d,f)=p^{min\{a,k-a\}}
gcd(d,f)=pmin{a,k−a}。但因为
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1,故
a
a
a的质因子里没有
p
p
p,即
g
c
d
(
d
,
f
)
∤
a
gcd(d,f)\nmid a
gcd(d,f)∤a,矛盾。故②得证。
由结论①②可知结论③:
b
b
b的质因子至少拥有两个。
根据③,我们设
b
=
∑
i
=
1
m
p
i
k
i
b=\sum_{i=1}^{m}p_{i}^{k_i}
b=∑i=1mpiki,令
d
=
p
1
k
1
,
f
=
b
/
d
,
d=p_{1}^{k_1},f=b/d,
d=p1k1,f=b/d,易知
g
c
d
(
d
,
f
)
=
1
gcd(d,f)=1
gcd(d,f)=1
故
c
f
−
d
e
=
a
cf-de=a
cf−de=a必有解,可以用扩展欧几里得求出
c
,
e
c,e
c,e。
需要注意的是,如果最后
c
<
0
,
e
>
0
c<0,e>0
c<0,e>0,其实不需要对扩展欧几里得的解做一些操作,只需要调换
c
/
d
,
e
/
f
c/d,e/f
c/d,e/f的位置即可。
AC代码(123ms)
#include <bits/stdc++.h>
using namespace std;
const int MAXN=5e6;
int prime[1000];//素数数组
bool is_prime[MAXN+10];//is_pri[i]表示i是否是素数
int sieve()//埃式筛
{
int n=MAXN;
int p=0;
for(int i=0; i<=n; i++)
is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
is_prime[2]=true;
for(int i=2; i<=sqrt(n); i++)
{
if (is_prime[i])
{
prime[++p]=i;
for(int j=2*i; j<=n; j+=i)
is_prime[j]=false;
}
}
return p;
}
long long extended_gcd(long long a, long long b, long long &x, long long &y)
//扩展gcd
{
long long r, t;
if (b==0)
{
x=1;
y=0;
return a;
}
r=extended_gcd(b, a%b, x, y);
t=x;
x=y;
y=t-(a/b)*y;
return r;
}
long long solve_exgcd(long long a, long long b, long long c, long long &x, long long &y)
{
long long p=extended_gcd(a, b, x, y);
if (c%p)
{
x=-1;
y=-1;
return -1;
}
x*=(c/p);
y*=(c/p);
return 0;
}
void solve1()
{
long long pp=sieve();
int t;
scanf("%d", &t);
while(t--)
{
long long a, b;
scanf("%lld%lld", &a, &b);
if (__gcd(a, b)!=1)// ka/kb
{
long long v=__gcd(a, b);
a/=v;
b/=v;
printf("%lld %lld %lld %lld\n", a+1, b, 1, b);
continue;
}
else
{
if (b==1 || is_prime[b])//特判无解情况1
{
printf("-1 -1 -1 -1\n");
continue;
}
long long sum=0;
long long tmp,time=0;
long long bb=b;
for(int i=1;i<=pp && bb!=1;i++)
{
if(bb%prime[i]==0)
{
tmp=prime[i];
while(bb%prime[i]==0)
{
bb/=prime[i];
time++;
}
break;
}
}
if(bb==1)//特判情况2
{
printf("-1 -1 -1 -1\n");
continue;
}
long long d=1;
for(int i=1; i<=time; i++)
{
d*=tmp;
}
// printf("d=%lld\n",d);
long long f=bb;
long long c=0, e=0;
solve_exgcd(f, d, a, c, e);
if (c<0 && e>0)
printf("%lld %lld %lld %lld\n", e, f, -c, d);//两个调过来
else
printf("%lld %lld %lld %lld\n", c, d, -e, f);
}
}
}
int main()
{
// ios_base::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long long test_index_for_debug=1;
char acm_local_for_debug;
while(cin>>acm_local_for_debug)
{
cin.putback(acm_local_for_debug);
if (test_index_for_debug>100)
{
throw runtime_error("Check the stdin!!!");
}
auto start_clock_for_debug=clock();
solve1();
auto end_clock_for_debug=clock();
cout<<"\nTest "<<test_index_for_debug<<" successful"<<endl;
cerr<<"Test "<<test_index_for_debug++<<" Run Time: "
<<double(end_clock_for_debug-start_clock_for_debug)/CLOCKS_PER_SEC<<"s"<<endl;
cout<<"--------------------------------------------------"<<endl;
}
#else
solve1();
#endif
return 0;
}
后记
赛时差一点就对了…
感谢赛后蔡队的指点 (CSLNB!)
DrGilbert 2020.7.18