T1.fuction

吐槽一波错误拼写

跟考场思路差不多,只不过细节挺多的呢。

判掉a=0,b=0,c=0的几种组合,还有负数的情况要打标记特殊处理。

然后就是一个拓欧啦,先求出g=gcd(a,b),顺便求出ax+by=g的x和y,然后根据裴蜀定理(或者是直觉),我们知道ax+by可以以g为长度遍历数轴,要是c%g!=0,那就无解了。

然后是可以整除的情况,就把x和y乘以d=c/g,这样就求出了ax+by=c的一组x和y了,定x为较小的数,把x补到正,同时y跟着减,要是x刚好到正,y已经负了,那就是无解。

还有,此时如果a和b是一正一负的,是无穷多解的,因为可以正负系数同时不断扩大。

然后剩下的情况,就是x和y都是正整数啦,此时为了满足ax+by=c,考虑有多少种等价情况,也就是x加上一个sa*x,y就得减去一个sb*y,显然sa=lcm(a,b)/a=b/g,同理sb=a/g

因为x是增大的,y是减小的,我们只需要判断y能减多少个sb就可以啦。

 

#include<iostream>
#include<cstdio>
#define NON puts("0"),0
#define INF puts("ZenMeZheMeDuo"),0
using namespace std;

const int MAX=65535;

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
  while(isdigit(c))ret=ret*10+c-'0',c=getchar();
  return ret*f;
}

typedef long long ll;

ll exgcd(ll A,ll B,ll &x,ll &y){
  if(!B) return x=1,y=0,A;
  ll ret=exgcd(B,A%B,y,x);
  y-=A/B*x;return ret;
}

ll T,a,b,c;

int solve(){
  a=rd();b=rd();c=rd();
  bool fa=0,fb=0;
  if(a<=0&&b<=0) a=-a,b=-b,c=-c;
  if(!a)if(c%b==0&&c/b>0) return INF;else return NON;
    if(!b)if(c%a==0&&c/a>0)return INF;else return NON;
  if(a==0&&b==0)return c?NON:INF;
  if(a==1&&b==1)return c>MAX-1?INF:printf("%lld\n",c-1);
  if(a<0) fa=1,a=-a;
  if(b<0) fb=1,b=-b;
  if(a+b==c)return puts("1"),0;
  ll x,y;
  ll g=exgcd(a,b,x,y);
  if(c%g) return NON;
  ll d=c/g;
  x*=d;y*=d;
  if(fa) a=-a,x=-x;
  if(fb) b=-b,y=-y;
  ll sa=b/g,sb=a/g;
  if(a*b<0) return INF;
  ll t=x/sa-1;
  if(x%sa==0) t--;
  x-=t*sa;y+=t*sb;
  if(x>sa) x-=sa,y+=sb;
  if(y<=0) return NON;
  ll ans=y/sb+(y%sb!=0);
  if(ans>MAX) return INF;
  printf("%lld\n",ans);
  return 0;
}

int main(){
  T=rd();
  while(T--) solve();
  return 0;
}
View Code

相关文章:

  • 2021-12-28
  • 2021-12-15
  • 2021-06-15
  • 2021-04-02
  • 2021-08-12
  • 2021-12-25
  • 2021-05-27
  • 2021-09-06
猜你喜欢
  • 2021-04-16
  • 2021-08-19
  • 2021-11-18
  • 2022-12-23
  • 2021-04-18
  • 2021-07-06
相关资源
相似解决方案