解这道题目之前,我们先来回顾一下我们的老题:青蛙的约会。http://poj.org/problem?id=1061
有两只青蛙A、B,他们在一条线上同向而行,A在X位置,每次跳M格,B在Y位置,每次跳N格。这条线有L长,首尾相连。为最少跳多少次他们会相遇在同一点。或者永远不能相见。Impossible。这就像我博客上的签名档:彼此追逐却有着永恒的距离。
我们可以根据这些条件列出一个方程出来:(X+M*t)%L=(Y+N*t)%L其中t代表跳了多少次。由同余定理可知:X+M*t=Y+N*t+k*L。这个k可正可负。由此可变化成我们熟悉的二元一次方程,运用扩展欧几里得求得解。
(N-M)*t+k*L=Y-X(其中只有t和k是未知数)即ax+by=gcd(a,b)。我们可以把a=N-M,b=Y-X.这样就变成a*t+k*L=b。根据扩展欧几里得可以求得a和k的值。但是这个a,k不是最小的整数解。这个方程最小整数解的条件是b % gcd(l,a)等于0.因为a,k分别得除以gcd(l,a)再乘上b,对应的才是方程式a*t+k*L=b的解。假设我们有最小整数解,我们怎么去解呢?我们设r=b / gcd(l,a).最小整数解应该是:t(min)=(t/gcd(l,a)*b % r+r)r.kmin=(b-a(min)*t)/L;好吧,我自己也有点说不清楚了,得自己用笔化化化。总之就是这样了。不懂的留言或者私聊。
(x1,y1)=(x0+b/gcd(a,b),y0-a/gcd(a,b))
#include <iostream>
#include <cstring>
using namespace std;
#define LL long long
LL x,y,gcd;
void exgcd(LL a,LL b)
{
if (b==0)
{
x=1;
y=1;
gcd=a;
return;
}
exgcd(b,a%b);
LL t=x;
x=y;
y=t-a/b*y;
return;
}
int main()
{
LL x1,y1,m,n,l;
while (cin>>x1>>y1>>m>>n>>l)
{
LL a=n-m;
LL b=x1-y1;
exgcd(l,a);
LL r=l/gcd;
if (b % gcd) cout<<"Impossible"<<endl;
else
cout<<(y*b/gcd % r+r) % r<<endl;
}
return 0;
}
Modified LCS |
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:65536KB |
Total submit users: 32, Accepted users: 21 |
Problem 12831 : No special judgement |
Problem description |
LCS stands for longest common subsequence, and it is a well known problem. A sequence in this problem means a list of integers, and a sequence X is considered a subsequence of another sequence Y, when the sequence X can be obtained by deleting zero or more elements from the sequence Y without changing the order of the remaining elements. |
Input |
Your program will be tested on one or more test cases. The first line of the input will be a single integer T, the number of test cases T ranges in(1,100). Followed by the test cases, each test case is described in one line which contains 6 integers separated by a single space N1 F1 D1 N2 F2 D2 (N1,N2 ranges in(1,10^18) and F1,D1,F2,D2 ranges in(1,10^9)) representing the length of the first sequence, the first element in the first sequence, the incremental value of the first sequence, the length of the second sequence, the first element in the second sequence and the incremental value of the second sequence, respectively. |
Output |
For each test case, print a single line which contains a single integer representing the length of the longest common subsequence between the given two sequences. |
Sample Input |
3 5 3 4 15 3 1 10 2 2 7 3 3 100 1 1 100 1 2 |
Sample Output |
4 3 50 |
Problem Source |
ACPC 2013 |
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
#define LL __int64
LL x,y,gcd;
void exgcd(LL a ,LL b)
{
if (!b)
{
x=1;
y=1;
gcd=a;
return;
}
exgcd(b,a%b);
LL t=x;
x=y;
y=t-a/b*y;
return ;
}
int main()
{
int T;
LL n1,n2,f1,f2,d1,d2;
// freopen("in.txt", "r", stdin);
// freopen("outt.txt","w",stdout);
scanf("%d",&T);
while (T--)
{
cin>>n1>>f1>>d1>>n2>>f2>>d2;
LL f=f2-f1;
exgcd(d1,-d2);
if (f % gcd)
{
puts("0");
continue;
}
else
{
LL r=abs((-d2)/gcd);
x=(x*f/gcd % r+r)%r;
y=(f-x*d1)/(-d2);
LL dx=abs(d1/gcd);
LL dy=abs(d2/gcd);
LL ans=min((n1-x-1)/dy,(n2-y-1)/dx)+1;
cout<<ans<<endl;
}
}
return 0;
}