zoukankan      html  css  js  c++  java
  • 扩展欧几里德--解的个数

    解的个数

    已知整数x,y满足如下面的条件:

      ax+by+c = 0

      p<=x<=q

      r<=y<=s

    求满足这些条件的x,y的个数。

    输入描述 Input Description

    第一行有一个整数nn<=10),表示有n个任务。n<=10

    以下有n行,每行有7个整数,分别为:a,b,c,p,q,r,s。均不超过108

    输出描述 

    n行,第i行是第i个任务的解的个数。

    样例输入 

    2

    2 3 -7 0 10 0 10

    1 1 1 -10 10 -9 9

    样例输出 

    1

    19

    #include<cstdio>
    #include<cmath>
    int x,y,a,b,c,n,g;
    long long ans,p,q,r,s;
    int exgcd(int a,int b,int *x,int *y)//拓展欧几里德; 
    {
     if(b==0){*x=1;*y=0;return a;}
     int d=exgcd(b,a%b,x,y);
     int z=*x;*x=*y;*y=z-*y*(a/b);
     return d;
    }
    void zhao1(int x,int y)
    {
     if((x<=q)&&(x>=p)&&(y>=r)&&(y<=s))ans++;
     if(x<=q){
      if(b/g>0){x+=b/g;y-=a/g;zhao1(x,y);}//别把zhao1 放外面,b/g=0时会被卡挂了; 
      else if(b/g<0){x-=b/g;y+=a/g;zhao1(x,y);}  
     }
    }
    void zhao2(int x,int y)
    {
     if((x<=q)&&(x>=p)&&(y>=r)&&(y<=s))ans++;
     if (x>=p){
      if(b/g>0){x-=b/g;y+=a/g;zhao2(x,y);}
      else if(b/g<0){x+=b/g;y-=a/g;zhao2(x,y);}  
     }
    }
    int main()
    {
     scanf("%d",&n);
     for(int i=1;i<=n;i++)
     {
      ans=0;
      scanf("%d%d%d%I64d%I64d%I64d%I64d",&a,&b,&c,&p,&q,&r,&s);
      if(s<r||q<p){printf("%I64d
    ",ans);continue;}//x或y的可行域不存在时,结果为0; 
      if(a==0&&b==0&&c==0) //a,b,c均为0时 ,x,y可以是任意值; 
       {s=s-r+1;q=q-p+1;ans=q*s;printf("%I64d
    ",ans);continue;}
      if(a==0&&b==0&&c!=0) //a=b=0,c!=0时 ,无解; 
       {printf("%I64d
    ",ans);continue;}
      c=-c;                //将c调到等号右边; 
      g=exgcd(a,b,&x,&y);  //找到a,b的最大公因数;并且找到一组ax+by=1的一组解; 
      x*=c/g;y*=c/g;       //得到ax+by=c时 的一组解; 
      if(a*x+b*y!=c)       //等号可能不成立,例2 0 1 ; 
           {ans=0;printf("%ld
    ",ans);continue;}
      zhao1(x,y);          //分别向x变大和变小的方向找在[p,q] 之间的解; 
      zhao2(x,y);
      if((x<=q)&&(x>=p)&&(y>=r)&&(y<=s)) ans-=1;//x,y符合要求时,两次递归多加了一次; 
      printf("%I64d
    ",ans);
     }
     return 0;
    }
     
    View Code

    //自认为要懂扩展欧几里德有点难,偷个懒,背个代码。。。。

  • 相关阅读:
    产生唯一的临时文件mkstemp()
    Linux文档时间戳查看和修改——stat
    Linux下快速查找文件
    Crypt加密函数简介(C语言)
    产生随机数 random
    见微知著——从《新闻联播》挖掘价值资讯擒拿年度政策受益牛股
    Linux中link,unlink,close,fclose详解
    不用输液
    javaScript document对象详解
    javascript初步了解
  • 原文地址:https://www.cnblogs.com/qingang/p/5178366.html
Copyright © 2011-2022 走看看