• 1352 集合计数 扩展欧几里德算法


    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1352

    题目的本意就是要求

    ax+by=n+1

    a * x + b * y = c,在x >= 1和y >= 1的条件下的解的个数。

    ①、等于0的情况是:

    1、方程无解,

    2、最小的解就是(1. 1),大家都是1倍,如果比c还大,那就是0

    3、设最小的解是x1,如果c - a * x1 < b,那也不行。也就是b不够一倍了。

    其他的:(设x1是最小的正整数解)

    通解就是x0 = x1 + b / (abgcd) * k,(k >= 0)

    然后带入去a * x + b * y = c,同样c - a * x1也是要大于等于b才行,因为起码都要一倍。

    然后解出的k,就是答案。包括上0,所以是k + 1

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    LL exgcd(LL a, LL mod, LL &x, LL &y) {
        //求解a关于mod的逆元     ★:当且仅当a和mod互质才有用
        if (mod == 0) {
            x = 1;
            y = 0;
            return a;//保留基本功能,返回最大公约数
        }
        LL g = exgcd(mod, a % mod, x, y);
        LL t = x;    //这里根据mod==0  return回来后,
        x = y;  //x,y是最新的值x2,y2,改变一下,这样赋值就是为了x1=y2
        y = t - (a / mod) * y;    // y1=x2(变成了t)-[a/mod]y2;
        return g;            //保留基本功能,返回最大公约数
    }
    
    bool get_min_number (LL a, LL b, LL c, LL &x, LL &y) { //得到a*x+b*y=c的最小整数解
        LL abGCD = __gcd(a, b);
        if (c % abGCD != 0) return false; //不能整除GCD的话,此方程无解
        a /= abGCD;
        b /= abGCD;
        c /= abGCD;
        LL tx, ty;
        exgcd(a, b, tx, ty); //先得到a*x+b*y=1的解,注意这个时候gcd(a,b)=1
        x = tx * c;
        y = ty * c;  //同时乘上c,c是约简了的。得到了一组a*x + b*y = c的解。
        LL haveSignB = b;
        if (b < 0) b = -b;     //避免mod负数啊,模负数没问题,模了负数后+负数就GG
        x = (x % b + b) % b;  //最小解
        if (x == 0) x = b; //避免x = 0不是"正"整数  不要用这个,溢出
        y = (c - a * x); // haveSignB;
        return true; //true代表可以
    }
    
    void work() {
        LL a, b, c;
        cin >> c >> a >> b;
        c++;
        if (c % __gcd(a, b) != 0 || a + b > c) {
            cout << 0 << endl;
            return;
        }
        LL x1, y1;
        get_min_number(a, b, c, x1, y1);
        LL t = c - b - a * x1;
        if (c - x1 * a < b) {
    //        cout << t << endl;
    //        cout << c << " " << a << " " << b << endl;
    //        while(1);
            cout << 0 << endl;
            return;
        }
        t /= a / __gcd(a, b) * b;
        cout << t + 1 << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        IOS;
        int t;
        cin >> t;
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    C#多线程学习(一) 多线程的相关概念
    如何:创建和终止线程(C# 编程指南)
    原来多线程中的join()是这么回事(转)
    c# 关于Task类处理多线程的学习
    C#多线程学习(四) 多线程的自动管理(线程池)
    【转】Java 四种引用
    【转】Java线程:新特征锁(1)
    Builder
    Proxy
    【转】Java NIO(一)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6376117.html
Copyright © 2020-2023  润新知