• HZOJ 方程的解


    乍一看还以为是道水题,没想到这玩意这么难搞。

    看题显然是exgcd,然而exgcd求的是一个解而不是解的个数(考试的时候不记得通解的式子然后挂了)。

    对于40%的数据,直接枚举计数即可。

    对于另为20%,a+b=c,puts("1");

    这60分差不多是送的。

    剩下的就是比较恶心的了:

    先讨论都是正数的情况:$ax+by=c$,exgcd可以求$ax+by=gcd(a,b)$的解x0,y0,设t=c/gcd(a,b);则$a*tx_0+b*ty_0=t*gcd(a,b)=c$.

    那么我们就求出了方程的一组特解,方程的通解为$x=x_0+kb,y=y_0-ka$,那么可以枚举k计数(加一些优化可以拿到这20分),但这样太慢。

    能不能不用枚举呢?a/=gcd(a,b),b/=gca(a,b),c/=gcd(a,b)=t;因为$x=x_0+kb$,将x0模b(如果<=0,+b),得到x0的最小正数解(此时k最小),$ax+by=c$得$y_0=(c-a*x_0)/b$,

    那么我们就的到了y0的最大解,y0%=a,那么我们得到了y0的最小正数解,则ans=(y0-miny)/a0+1

    那么对于负数呢?

    只需要将a,b变为正数求解,之后将a,b与求得的x0,y0同乘-1,等式仍然成立。

     推荐一个博客

     1 #include<iostream>
     2 #include<cstdio>
     3 #define LL long long
     4 #define int LL
     5 using namespace std;
     6 int T,a,b,c;
     7 int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
     8 int exgcd(int a,int b,int &x,int &y)
     9 {
    10     if(!b){x=1,y=0;return a;}
    11     int gcd=exgcd(b,a%b,x,y),t=x;
    12     x=y,y=t-a/b*y;
    13     return gcd;
    14 }
    15 inline int read();
    16 signed main()
    17 {    
    18 //    freopen("in.txt", "r", stdin);
    19  //   freopen("0.out", "w", stdout);
    20     cin>>T;
    21     while(T--)
    22     {
    23         cin>>a>>b>>c;
    24         if(a==0&&b==0&&c==0){puts("ZenMeZheMeDuo");continue;}
    25         if(a==0&&b==0&&c!=0){puts("0");continue;}
    26         if(a==0&&c==0){puts("ZenMeZheMeDuo");continue;}
    27         if(a==0&&c%b==0&&c/b>0){puts("ZenMeZheMeDuo");continue;}
    28         if(a==0){puts("0");continue;}
    29         if(b==0&&c==0){puts("ZenMeZheMeDuo");continue;}
    30         if(b==0&&c%a==0&&c/a>0){puts("ZenMeZheMeDuo");continue;}
    31         if(b==0){puts("0");continue;}
    32         if(a<0&&b<0&&c<0){a=-a,b=-b,c=-c;}
    33         if(a==1&&b==1)//
    34         {
    35             if(c>=65536){puts("ZenMeZheMeDuo");continue;}
    36             else {printf("%lld
    ",c-1);continue;}
    37         }    
    38         if(a+b==c){puts("1");continue;}
    39         if(a<=1000&&b<=1000&&c<=1000&&a>0&&b>0&&c>0)//
    40         {
    41             int ans=0;
    42             for(int x=1;x<=c;x++)
    43             {
    44                 for(int y=1;y<=c;y++)
    45                 {
    46                     if(a*x+b*y==c)ans++;
    47                     if(ans>=65536)break;    
    48                 }    
    49                 if(ans>=65536)break;
    50             }
    51             if(ans>=65536){puts("ZenMeZheMeDuo");continue;}
    52             else {printf("%lld
    ",ans);continue;}
    53         }
    54         else
    55         {
    56             int fa=0,fb=0;
    57             if(c<0)a=-a,b=-b,c=-c;
    58             if(a<0)a=-a,fa=1;
    59             if(b<0)b=-b,fb=1;
    60             int GCD=gcd(a,b);
    61             if(c%GCD!=0){puts("0");continue;}
    62             int t=c/GCD,x0,y0;
    63             exgcd(a,b,x0,y0);x0*=t;y0*=t;
    64             int a0=a/GCD,b0=b/GCD;c=t;
    65             if(fa)a0=-a0,x0=-x0;
    66             if(fb)b0=-b0,y0=-y0;
    67             if(a0<0)a0=-a0,b0=-b0,c=-c;
    68             if(a0*b0<0){puts("ZenMeZheMeDuo");continue;}
    69             x0=x0%b0;
    70             if(x0<=0)x0+=b0;
    71             y0=(c-a0*x0)/b0;
    72             if(y0<0){puts("0");continue;}
    73             LL miny=y0%a0;
    74             if(miny==0)miny+=a0;//
    75             if(miny>y0){puts("0");continue;}
    76             else 
    77             {
    78                 int ans=(y0-miny)/a0+1;
    79                 if(ans>=65536){puts("ZenMeZheMeDuo");continue;}
    80                 else {printf("%lld
    ",ans);continue;}
    81             }
    82         }
    83     }
    84 }
    85 inline int read()
    86 {
    87     int s=0,f=1;char a=getchar();
    88     while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();}
    89     while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
    90     return s*f;
    91 }
    View Code
  • 相关阅读:
    Linux内核(5)
    Linux内核(4)
    Linux内核(3)
    Linux内核(2)
    Linux内核(1)
    Linux时间子系统(十七) ARM generic timer驱动代码分析
    Linux时间子系统(十六) clockevent
    Linux时间子系统(十五) clocksource
    Linux时间子系统(十四) tick broadcast framework
    Linux时间子系统(十三) Tick Device layer综述
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11227940.html
Copyright © 2020-2023  润新知