HDUoj6624 fraction(辗转相除法)

HDUoj6624 fraction(辗转相除法)

题目大意

给出一个p和x要求求出最小的b满足
a ≡ b x ( m o d   p ) a\equiv bx(mod\ p) abx(mod p)

解题思路

先对原式进行一些转化
a ≡ b x ( m o d   p ) a = b x − p c ( c ∈ Z ) ∵ 0 ≤ a < b → 0 ≤ b x − p c < b → p x ≤ b c < p x − 1 \begin{aligned} a&\equiv bx(mod\ p)\\ a&=bx-pc(c\in Z)\\ \because &0\le a<b\\ \rightarrow &0\le bx-pc<b\\ \rightarrow&\frac{p}{x}\le \frac{b}{c}<\frac{p}{x-1} \end{aligned} aabx(mod p)=bxpc(cZ)0a<b0bxpc<bxpcb<x1p
原问题就转化成了一个经典问题,求满足值在所给的两分数之间时,最小的分子分母是多少。

⌈ p x ⌉ = d \left\lceil\frac{p}{x}\right\rceil=d xp=d,当 ⌊ p x − 1 ⌋ ≥ d \left\lfloor\frac{p}{x-1}\right\rfloor\ge d x1pd时,显然有b=d,c=1为最优解,但是当不满足这个条件时,首先可以发现 p x \frac{p}{x} xp p x − 1 \frac{p}{x-1} x1p之间的差值必然小于1,由此
p x − ( d − 1 ) ≤ b c − ( d − 1 ) < p x − 1 − ( d − 1 ) \begin{aligned} \frac{p}{x}-(d-1)\le \frac{b}{c}-(d-1)<\frac{p}{x-1}-(d-1) \end{aligned} xp(d1)cb(d1)<x1p(d1)
此时可以发现不等式外侧的两个值都变成了真分数,只要对其作倒数就又变成了假分数则又可以进行上述操作,最终到达满足条件的答案再倒退回来就是答案

AC代码

#include
using namespace std;
typedef long long LL;
LL p,a;
//solve "pa/pb
void solve(LL pa,LL pb,LL qa,LL qb,LL &x,LL &y)
{
	LL z=(pa+pb-1)/pb;
	if(z<=qa/qb){
		x=z;y=1;
		return ;
	}
	pa-=(z-1)*pb;qa-=(z-1)*qb;
	solve(qb,qa,pb,pa,y,x);
	x+=(z-1)*y;
}
int main()
{
	int t;
	scanf("%d",&t);
	LL x,y;
	while(t--)
	{
		scanf("%lld%lld",&p,&a);
		solve(p,a,p,a-1,x,y);
		printf("%lld/%lld\n",x*a-p*y,x);
	}
}

你可能感兴趣的:(数学)