zoukankan      html  css  js  c++  java
  • sgu 106 the equation

         the equation

      题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=10789 

      先解释题意:首先给你三个数 a b c 有ax+by+c=0,然后给你x和y的范围x1,x2,y1,y2,求在这个范围内有多少对(x,y)是满足条件的。。。

      思路: 如果抛开时间复杂度的话,这道是很简单的题,可以说是线性同余的模板题了,直接求出初始的x,然后先通过加减b/(a,b)使x成为>=x1的最小一个,然后再加b/(a,b)趋近x2,在这个过程再判断对应的y是否满足条件。这是很容易想到的方法,而且看起来时间复杂度也只有O(n),但事实就是:这样是会超时的。。也就是说上面的那段话都是无用的...0.0...

      当然,另找思路这道题也不难嘛,由于所有x、y都是由一个数加减得来,而且刚开始那对满足条件,加减同样次数得到的还是一对,对,他们还是匹配的,他们存在递推公式: x=xt+k*b/(a,b);  y=yt-k*a/(a,b); 也就是说,只要k是一样的,那么满足两个方程的x,y就是一对...

      首先还是确定一个大于等于x1的最小x,用k1记住现在的他是由初始值加上多少倍的b/(a,b)得来,然后再找范围内最大的x,同样,标记k2,对y也用k3、k4来标记最小和最大y,然后就比如k1,k2->(1,10),k3,k4->(4,16),那么从第四对到第10对满足条件(x,y都在范围内。。。),所以答案就等于 k2-k3+1;

      思路讲完了,可以写代码了,悄悄告诉你们,我在 acm.hust.edu.cn 错了快70次,是看着那个[Wrong answer on test x]从1个慢慢涨到AC的...写了一整天,智商果然不给力啊..0.0...得出一个经验:第十三个样例多半是a=0、b=0的情况,如果卡在第十三个样例,就试试改改这个。。同时他后台数据还不是很给力,估计没有a==0&&b!=0 、a!=0&&b==0,这两种情况的样例,即使你们在这两个条件中把次数填为10086也不会错的。。。

      

      1 #include<stdio.h>
      2 typedef long long LL;
      3 void exGcd(LL a,LL b,LL &d,LL &x,LL &y)
      4 {
      5   if(b==0)
      6   {
      7     d=a;
      8     x=1;
      9     y=0;
     10     return ;
     11   }
     12   exGcd(b,a%b,d,x,y);
     13   LL t=x;
     14   x=y;
     15   y=t-a/b*y;
     16 }
     17 LL max(LL a,LL b)
     18 {
     19   return a>b?a:b;
     20 }
     21 LL min(LL a,LL b)
     22 {
     23   return a<b?a:b;
     24 }
     25 int main()
     26 {
     27   LL a,b,c,x1,x2,y1,y2,tmp,d,x,y;
     28   while(scanf("%I64d%I64d%I64d",&a,&b,&c)!=EOF)
     29   {
     30     scanf("%I64d%I64d",&x1,&x2);
     31     scanf("%I64d%I64d",&y1,&y2);
     32     c=-c; //把c移到方程右边
     33     LL k1,k2,k3,k4,co=0;
     34     if(a==0&&b==0) 
     35     {
     36       if(c==0)
     37         co=(y2-y1+1)*(x2-x1+1);
     38     }
     39     else if(a==0)
     40     {
     41       if(c%b==0)
     42       {
     43         tmp=c/b;
     44         if(tmp>=y1&&tmp<=y2) co=(x2-x1)+1;
     45       }
     46     }
     47     else if(b==0)
     48     {
     49       if(c%a==0)
     50       {
     51         tmp=c/a;
     52         if(x1<=tmp&&tmp<=x2) co=(y2-y1)+1;
     53       }
     54     }
     55     else
     56     {
     57       exGcd(a,b,d,x,y);
     58       if(c%d==0)  // 不能整除代表无解 
     59       {
     60         x=x*(c/d);
     61         y=y*(c/d);
     62         LL xt=x,yt=y;
     63         LL mx=b/d,my=a/d;
     64         mx=mx>0?mx:-mx;   //避免麻烦,就全部弄成正的  
     65         my=my>0?my:-my;
     66         if(x>=x1)
     67         {
     68           x=x-(x-x1)/mx*mx; //如果x大于x1,就不断减少,直到最接近或等于x1
     69         }
     70         else
     71         {
     72           x=x+(x1-x)/mx*mx; //接近x1
     73           if(x<x1) x+=mx;   //如果x还小于x1,就再加一次
     74         }
     75         k1=(x-xt)/(b/d);    //记录k,我们暂且完全抛弃什么正负,反正照着公式算绝对不会错
     76         if(x>=x2)           //同上
     77         {
     78           x=x-(x-x2)/mx*mx;
     79           if(x>x2) x-=mx;
     80         }
     81         else
     82         {
     83           x=x+(x2-x)/mx*mx;
     84         }
     85         k2=(x-xt)/(b/d);
     86         if(y>=y1)
     87         {
     88           y=y-(y-y1)/my*my;
     89         }
     90         else
     91         {
     92           y=y+(y1-y)/my*my;
     93           if(y<y1) y+=my;
     94         }
     95         k4=(y-yt)/(-a/d);
     96         if(y>=y2)
     97         {
     98           y=y-(y-y2)/my*my;
     99           if(y>y2) y-=my;
    100         }
    101         else
    102         {
    103           y=y+(y2-y)/my*my;
    104         }
    105         k3=(y-yt)/(-a/d);
    106         //到此,k1,k2,k3,k4全部求出来,然后要注意某些情况可能使得k2<k1,负的哦。。
    107         co=min(k4,k2)-max(k3,k1)+1;
    108         //if(co<0) co=0;
    109         if(co<0) co=-co+2;  //把它变为正的,同时加上多减的1
    110         //printf("mx = %I64d	my = %I64d
    ",mx,my);  帮助找错的。。
    111         //printf("xt = %I64d	k1 = %I64d	k2 = %I64d
    yt = %I64d	k3 = %I64d	k4 = %I64d
    ",xt,k1,k2,yt,k3,k4);
    112       }
    113     }
    114     printf("%I64d
    ",co);
    115   }
    116   return 0;
    117 }

      上面说出现k2<k1的情况看这个。。。

      同时,本渣由于无心细细研究,这思路这代码只保证AC,不保证无错,也有可能是后台数据太lou,等以后再细研吧...

      

  • 相关阅读:
    Linux命令之du命令
    6562. 【GDOI2020模拟4.15】楼房搭建(building)
    CF660E. Different Subsets For All Tuples
    6555. 【GDOI2020模拟4.11】黑红兔(brr)(SAM小技♂巧)
    6554. 【GDOI2020模拟4.11】赢家(winner)
    6553. 【GDOI2020模拟4.11】人生(life)
    6546. 【GDOI2020模拟4.8】USACO 2020 Open Contest, Platinum(circus)
    6545. 【GDOI2020模拟4.8】USACO 2020 Open Contest, Platinum(exercise)
    6544. 【USACO 2020 US Open Platinum】 Sprinklers 2: Return of the Alfalfa
    6543. 【GDOI2020模拟4.4】Easy Data Structure(动态dp)
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/4729996.html
Copyright © 2011-2022 走看看