题目: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