题目:Modified LCS
为过此题去仔细研究了下扩展欧几里德算法,领悟了一些精华。
模板为:
void gcd(ll a, ll b, ll& d, ll& x, ll& y)
{
if(!b) {d = a; x = 1; y = 0;}
else{ gcd(b, a%b, d, y, x); y -= x*(a/b);}
}
这里算出来的x,y是对于方程ax+by=gcd(a,b)而言的一组解。if(!b) {d = a; x = 1; y = 0;} 当b=0时,a = gcd(a,b),ax+by=gcd(a,b)这个方程就变为ax=a了,即x=1,y等于几其实是随便的,但是必须要有数字为了反推出之前的解,这里就为了简洁就等于0。PS:可以尝试不填0说不定靠点运气能提高效率(玩笑)。else{ gcd(b, a%b, d, y, x); y -= x*(a/b);} gcd(b, a%b, d, y, x);
y -= x*(a/b);
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<ctime>
using namespace std;
#define ll long long
void gcd(ll a, ll b, ll& d, ll& x, ll& y)
{
if(!b) {d = a; x = 1; y = 0;}
else{ gcd(b, a%b, d, y, x); y -= x*(a/b);}
}
int main()
{
ll n1,f1,d1,n2,f2,d2;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&n1,&f1,&d1,&n2,&f2,&d2);
ll x,y,g;
gcd(d1,-d2,g,x,y);
ll f = f2-f1;
x *= f/g;//小心溢出
y *= f/g;
g = abs(g);
ll a = d1/g;
ll b = d2/g;
if(x < 0 || y < 0)
{
while(x < 0 || y < 0)
{
x += b;
y += a;
}
}
else
{
while(x >= 0 && y >= 0)
{
x -= b;
y -= a;
}
x += b;
y += a;
}
ll num1 = (n1-1-x)/b;
ll num2 = (n2-1-y)/a;
printf("%lld\n",min(num1,num2)+1);
}
return 0;
}
/**************************************************************
Problem: 1446
User: HNU_TEAM_3
Language: C++
Result: Accepted
Time:0 ms
Memory:1484 kb
****************************************************************/Modified LCS (扩展欧几里德)细写了对这个算法思路的理解,布布扣,bubuko.com
Modified LCS (扩展欧几里德)细写了对这个算法思路的理解
原文地址:http://blog.csdn.net/glqac/article/details/26515207