zoukankan      html  css  js  c++  java
  • 51nod 1352 集合计数(扩展欧几里得)

    传送门

    题意

    分析

    即求ax+by=n+1的所有正整数对解

    我们可以求出最小的x 然后每lcm(a,b)个数,又满足ax+by==n+1 且 x,y均为整数
    所以就是裸的扩展欧几里得算法了

    对上述做一些说明
    1.如何求最小的x?
    做一遍ex_gcd(a,b,x,y),得到x,y,让x±(b/gcd(a,b))得到最小正整数x
    2.为什么是lcm个数
    (a*(x+b/gcd(a,b)*t)+b*(y-a/gcd(a,b)*t)=n+1)
    (a*(x+lcm)+b*(y-lcm)=n+1)
    3.注意求个数时(n+1-ax)%lcm非0要加1

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define F(i,a,b) for(int i=a;i<=b;++i)
    #define R(i,a,b) for(int i=a;i<b;++i)
    #define mem(a,b) memset(a,b,sizeof(a))
    
    int t;
    ll n,a,b;
    ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); }
    void ex_gcd(ll a,ll b,ll &x,ll &y)
    {
        if(b==0)
        {
            x=1,y=0;return ;
        }
        ex_gcd(b,a%b,x,y);
        ll tmp=x;
        x=y;
        y=tmp-(a/b)*y;
    }
    int main()
    {
        for(scanf("%d",&t);t--;)
        {
            scanf("%lld %lld %lld",&n,&a,&b);
            n++;
            ll g=gcd(a,b);
            if(n%g) { puts("0");continue; }
            ll x,y;
            ex_gcd(a,b,x,y);//求出的是a*x+b*y=gcd(a,b)
            ll lcm=a/g*b;
            x*=n/g;
            ll B=b/g;
            x=(x%B+B)%B;
            if(x==0) x+=B;
            y=n-x*a;
            if(y<0) puts("0");
            else printf("%lld
    ",(y%lcm)?y/lcm+1:y/lcm);
        }
        return 0;
    }
    
  • 相关阅读:
    约数
    质数
    回炉重造之重读Windows核心编程-018-堆栈
    回炉重造之重读Windows核心编程-017- 内存映射文件
    换电脑遇到git的一些记录
    python3之迭代器和生成器
    python3之类和对象
    python3之错误和异常
    python3之函数
    python3之流程控制
  • 原文地址:https://www.cnblogs.com/chendl111/p/7603742.html
Copyright © 2011-2022 走看看