• Two Arithmetic Progressions (exgcd的一些注意事项


    题意:You are given two arithmetic progressions: a1k + b1 and a2l + b2. Find the number of integers x such that L ≤ x ≤ R and x = a1k' + b1 = a2l' + b2, for some integers k', l' ≥ 0。

    分析:

    化为  a1k - a2l  =  b2- b1 求解二元一次不定方程,看正整数解x,y分别代入后有多少落在L,R之间,取最小的为答案即可

    but,思路很简单的一道题,却因为以下错误debug了一上午

    1, Q:ax - by =c 与  ax + by =c 解的不同

    觉得这两个一样,所以写的 exgcd( a1 ,a2 ,b2-b1 ,x ,y)

    事实是:对于求x的最小正整数解,这两个是一样的 ,对于求y的最小正整数解,这两个不一样

    所以这道题 应该写成exgcd( a1 ,-a2 ,b2-b1 ,x ,y)

    2,c++对于负数的取余规则

    c++取余结果是这样的 : a%b = (a的符号)(abs(a)%abs(b)),这跟数论负数取余规则不一样,所以要避免对负数取余情况的发生

    bool lieu( ll a ,ll b ,ll c ,ll &x ,ll &y ){
        g = ex_gcd( a ,b ,x ,y );
        if( c%g ) return 0;
        ll k = c/g ;
        mb = abs(a/g) ,ma = abs(b/g);
        x *= k; y *= k;
        x = (x%ma + ma)%ma;
            y = (y%mb + mb)%mb;
        return 1;
    }

    开始没注意通解的模ma,mb的正负, 以后这个模板这里都要加abs()

    #include <bits/stdc++.h>
    #define mem( a ,x ) memset( a ,x ,sizeof(a))
    #define rep( i ,x ,y ) for( int i = x ; i <= y ; i++ )
    using namespace std;
    
    typedef long long ll;
    
    
    ll L ,R ,n ,a1 ,a2 ,b1 ,b2;
    ll g ,ma ,mb;
    
    ll ex_gcd( ll a ,ll b ,ll &x ,ll &y ){
        if( !b ){
            x = 1; y = 0; return a;
        }
        ll d = ex_gcd( b ,a%b ,x ,y );
        ll t = x;
        x = y;
        y = t - a/b * y;
        return d;
    }
    
    bool lieu( ll a ,ll b ,ll c ,ll &x ,ll &y ){
        g = ex_gcd( a ,b ,x ,y );
        if( c%g ) return 0;
        ll k = c/g ;
        //模板修正 :加abs 
        mb = abs(a/g) ,ma = abs(b/g);
        x *= k; y *= k;
        x = (x%ma + ma)%ma;
        y = (y%mb + mb)%mb;
        return 1;
    }
    
    
    int main( ){
        ll ans1 = 0 ,ans2 = .0;
        cin >>a1 >>b1 >>a2 >>b2 >>L >>R;
        ll x ,y ,l1 ,r1 ,l2 ,r2;
        //cout<< (-6)%4 <<endl;
        if( lieu(a1 ,-a2 ,b2-b1 ,x ,y ) ){
            x = a1*x + b1;
            y = a2*y + b2;
            
            ma = abs(ma*a1);
            mb = abs(mb*a2);
                    
            l1 = max( 1ll*0 ,L - x) ,r1 = R - x;
            l2 = max( 1ll*0 ,L - y) ,r2 = R - y;
            
            if( r1 >=0 ){
            l1 = (l1/ma*ma) < l1 ? (l1/ma*ma)+ma : (l1/ma*ma);
            r1 = (r1/ma*ma);
            ans1 = (r1-l1)/ma+1;
             }
             
             if( r2 >=0 ){
            l2 = (l2/mb*mb) < l2 ? (l2/mb*mb)+mb : (l2/mb*mb);
            r2 = (r2/mb*mb);
            ans2 = (r2-l2)/mb+1;
            }
        }
        printf("%lld" ,min( ans2 ,ans1) );
        return 0;
    }
  • 相关阅读:
    MySQL的安装、配置与升级(版本5.x至8.x)
    Terra CW20 合约一致性对比和审计要点(一)
    ERC20代币审计流程
    非常道中小软件公司项目管理(3.3 项目外部关键成功因素)
    window bat 捕获执行失败
    批量把16进制转成10进制(c++)特别长的16进制字符串
    爱奇艺2020校招Java方向笔试题
    2020奇安信秋招Java方向试卷3
    Unity 之残影实现
    notepad++免安装版以及c/c++环境配置
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11368113.html
Copyright © 2020-2023  润新知