csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

来源:互联网 发布:淘宝申请介入要几天 编辑:程序博客网 时间:2024/06/05 14:24
这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉
这也是自己独自做扩展欧几里得算法的题目
题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解
下面介绍一下exgcd的一些知识点:求ax + by = c的解
一、首先求ax + by = gcd(a,b)的解 这个只要用exgcd的模板就可以求出来,设求得的解为x0,y0,
那么其他解为x = x0 + b/gcd(a,b)*t; y = y0 - a/gcd(a,b);(t为任意整数)
二、如果c % gcd(a,b) 不为0,那么ax + by = c无解;否则ax + by = c的解表示为x1 = x0*c/(gcd(a,b)),y1 = y0*c/gcd(a,b)
那么其他解为x = x1 + b/gcd(a,b); y = y1 - a/gcd(a,b);
如果了解了这些知识点,那么就可以解这个题目了

代码如下(附注释):

#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<time.h>#include<math.h>#define ll long long#define inf 0x7fffffff#define eps 1e-9#define pi acos(-1.0)#define P system("pause")using namespace std;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(){//freopen("input.txt","r",stdin);//freopen("output.txt","w",stdout);    ios::sync_with_stdio(false);    int t;    cin>>t;    while(t--)    {         ll n1,n2,f1,f2,d1,d2;         ll d, x, y, temp;         cin>>n1>>f1>>d1>>n2>>f2>>d2;//求d1*x - d2*y = f2- f1 ;                                     // x属于0---n1-1,y属于0---n2-1          gcd(d1, -d2, d, x, y);            ll c = f2 - f1;         if(c % d){              cout<<"0\n"<<endl;              continue;              }                   ll x1, y1;         x1 = x*(c/d);//d1*x - d2*y = f2- f1 的一组解          y1 = y*(c/d);   //     cout<<x1<<" "<<y1<<endl;                   ll k1, k2;         k1 = d2/abs(d);//y = kx + b中的k ,k > 0          k2 = d1/abs(d);                  if(x1 < 0 || y1 < 0)//求最小整数解          {               int i = 1;                while(1)               {                    if(x1 + k1*i >=0 && y1 + k2*i >=0)                       break;                     i++;                          }                     x1 = x1 + k1*i;               y1 = y1 + k2*i;         }         else         {             int i = 1;             while(1)             {                  if(x1 - k1*i < 0 || y1 - k2*i < 0)                     break;                  i++;                        }                 x1 = x1 - k1*(i-1);             y1 = y1 - k2*(i-1);         }//最小整数解为x1,y1      //    cout<<x1<<" "<<y1<<endl;                   if(x1 > n1-1 || y1 > n2 -1)         {               cout<<0<<endl;                continue;              }//         ll t1,t2;         t1 = (n1 - 1 - x1)/k1;//求的在[0,n1-1]区间内的解的个数         t2 = (n2 - 1 - y1)/k2;//求的在[0,n2-1]区间内的解的个数           cout<<min(t1,t2)+1<<endl;                                          }   // P;                                   return 0;    }


0 0