zoukankan      html  css  js  c++  java
  • TJOI2009 猜数字

    https://www.luogu.org/problemnew/show/P3868

    题目

    现有两组数字,每组k个,第一组中的数字分别为:a1,a2,...,ak表示,第二组中的数字分别用b1,b2,...,bk表示。其中第二组中的数字是两两互素的。求最小的非负整数n,满足对于任意的i,n - ai能被bi整除。

    所有数据中,第一组数字的绝对值不超过$10^9$(可能为负数),第二组数字均为不超过6000的正整数,且第二组里所有数的乘积不超过$10^{18}$

    题解

    孙子定理的练手题……

    套公式,解是

    [xequiv sum_{i=i}^n M_iM'_ia_ipmod{prod_{i=1}^nb_i}]

    其中

    [M_i=frac{prod_{j=1}^nb_j}{b_i},M'_iM_iequiv1pmod{b_i}]

    那么直接求和就好了,还需要注意爆long long(通过qmul解决),用qmul需要注意乘号右边不能小于0,否则是未定义行为……(G++直接死循环)

    求逆的时候需要注意不能直接用费马小定理,因为b不一定是素数,$varphi(b) e{b-1}$!

    所以只能用EXGCD,但是还是要注意得出来的结果并不保证大于0,所以放右边要注意换为大于0的数字(就算放左边a又要小于0,需要处理a了……)

    AC代码

    #include<cstdio>
    #include<cstdlib>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #define REP(r,x,y) for(register int r=(x); r<(y); r++)
    #define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
    #define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
    #ifdef sahdsg
    #define DBG(...) printf(__VA_ARGS__),fflush(stdout)
    #else
    #define DBG(...) (void)0
    #endif
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    char ch; int si;
    
    #define gc() getchar()
    
    template<class T>
    inline void read(T &x) {
        x=0; si=1; for(ch=gc();!isdigit(ch) && ch!='-';ch=gc());
        if(ch=='-'){si=-1,ch=gc();} for(;isdigit(ch);ch=gc())x=x*10+ch-'0';
        x*=si;
    }
    template<class T, class...A> inline void read(T &x, A&...a){read(x); read(a...);}
    
    inline LL qmul(LL a, LL b, LL p) {
        LL ans=0;
        for(;b;b>>=1) {
            if(b&1) ans=(ans+a)%p;
            a=(a*2)%p;
        }
        return ans;
    }
    
    inline void exgcd(LL a, LL b, LL &x, LL &y) {
        if(b==0) {x=1, y=0; return;}
        exgcd(b,a%b,y,x);
        y-=a/b*x;
        //return d;
    }
    
    
    #define MAXN 17
    LL a[MAXN],b[MAXN],M[MAXN],M_[MAXN];
    LL B=1;
    int main() {
    #ifdef sahdsg
        freopen("in.txt","r",stdin);
    #endif
        int k; read(k);
    
        REP(i,0,k) {read(a[i]);}
        REP(i,0,k) {read(b[i]); B*=b[i];}
        LL ans=0;
        REP(i,0,k) {
            //B/b[i] === 1 mod b[i]
            //B/b[i]x+b[i]*y=1
            LL x,t;
            exgcd(B/b[i],b[i],x,t);
            x%=B; if(x<0) x+=B;
            ans=(ans+qmul(B/b[i]*a[i],x,B))%B;
        }
        if(ans<0) ans+=B;
        printf("%lld
    ", ans);
        return 0;
    }
    

     但实际上孙子定理还没有完……还得继续仔细看数论讲义

  • 相关阅读:
    彻底理解Python中的yield
    python红包随机生成(隔板法)
    闭包的作用
    logging模块
    Python的datetime模块分析
    坑集系列
    Goertzel Algorith(戈策尔算法)用于检出特定输入频率
    Java学习个人笔记(一)配置java环境变量(Feb04,2013 )
    使用Gnu gprof进行Linux平台下的程序分析
    关于微编程(Microprogramming)的简史
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10816765.html
Copyright © 2011-2022 走看看