CRT(中国剩余定理)学习笔记

先扔个模板题。链接
简化题意:他让我求 \(x \equiv a_i \pmod{m_i}\) 的解。
例如,\( \begin{cases} x \equiv 1 \pmod{3} \\ x \equiv 1 \pmod{5} \\ x \equiv 2 \pmod{7} \end{cases} \) 这是样例。
\(M=m_1m_2\ldots m_n,M_i=M/m_i\)
显然 \(\gcd(M_i,m_i)=1\),所以 \(M_i\) 关于 \(m_i\) 的逆元存在,将其设为 \(t_i\)
于是有 \(M_it_i \equiv 1 \pmod{m_i},M_it_i \equiv 0 \pmod{m_j}(j\ne i)\)
把上面每个式子左右两边同乘 \(a_i\) ,就得到 \(M_it_ia_i \equiv a_i \pmod{m_i},M_it_ia_i \equiv 0 \pmod{m_j}(j\neq i)\)
然后你惊奇的发现答案出来了。
代码:

#include<stdio.h>
#define reg register
#define ri reg int
#define rep(i, x, y) for(ri i = x; i <= y; ++i)
#define nrep(i, x, y) for(ri i = x; i >= y; --i)
#define DEBUG 1
#define ll long long
#define il inline
#define max(i, j) (i) > (j) ? (i) : (j)
#define min(i, j) (i) < (j) ? (i) : (j)
#define read(i) io.READ(i)
#define print(i) io.WRITE(i)
#define push(i) io.PUSH(i)
struct IO {
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
  char buf[MAXSIZE], *p1, *p2;
  char pbuf[MAXSIZE], *pp;
#if DEBUG
#else
  IO() : p1(buf), p2(buf), pp(pbuf) {}
  ~IO() {
    fwrite(pbuf, 1, pp - pbuf, stdout);
  }
#endif
  inline char gc() {
#if DEBUG
    return getchar();
#endif
    if(p1 == p2)
      p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
    return p1 == p2 ? ' ' : *p1++;
  }
  inline bool blank(char ch) {
    return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
  }
  template <class T>
  inline void READ(T &x) {
    register double tmp = 1;
    register bool sign = 0;
    x = 0;
    register char ch = gc();
    for(; !isdigit(ch); ch = gc())
      if(ch == '-') sign = 1;
    for(; isdigit(ch); ch = gc())
      x = x * 10 + (ch - '0');
    if(ch == '.')
      for(ch = gc(); isdigit(ch); ch = gc())
        tmp /= 10.0, x += tmp * (ch - '0');
    if(sign) x = -x;
  }
  inline void READ(char *s) {
    register char ch = gc();
    for(; blank(ch); ch = gc());
    for(; !blank(ch); ch = gc())
      *s++ = ch;
    *s = 0;
  }
  inline void READ(char &c) {
    for(c = gc(); blank(c); c = gc());
  }
  inline void PUSH(const char &c) {
#if DEBUG
    putchar(c);
#else
    if(pp - pbuf == MAXSIZE) {
      fwrite(pbuf, 1, MAXSIZE, stdout);
      pp = pbuf;
    }
    *pp++ = c;
#endif
  }
  template <class T>
  inline void WRITE(T x) {
    if(x < 0) {
      x = -x;
      PUSH('-');
    }
    static T sta[35];
    T top = 0;
    do {
      sta[top++] = x % 10;
      x /= 10;
    } while(x);
    while(top)
      PUSH(sta[--top] + '0');
  }
  template <class T>
  inline void WRITE(T x, char lastChar) {
    WRITE(x);
    PUSH(lastChar);
  }
} io;
ll a[20], m[20], _M = 1, M[20], t[20];
void Exgcd(ll a, ll b, ll &x, ll &y) { 
  if (!b) x = 1, y = 0;
  else Exgcd(b, a % b, y, x), y -= a / b * x;
}
int main() {
  int n;
  ll x = 0, y = 0, ans = 0;
  read(n);
  rep(i, 1, n) read(m[i]), read(a[i]), _M *= m[i];
  rep(i, 1, n) M[i] = _M / m[i];
  rep(i, 1, n) {
    x = 0, y = 0;
    Exgcd(M[i], m[i], x, y);
    t[i] = x < 0 ? x + m[i] : x;
  }
  rep(i, 1, n) ans += (a[i] * M[i] * t[i]), ans %= _M;
  print(ans > 0 ? ans : ans + _M);
  return 0;
}

附:逆元 (数年前的笔记)

\(C^m_n = C^{n-m}_n = {n! \over m! \times (n-m)!}\)
如果\(n \times m \equiv 1 \pmod{p}\),那么我们称\(m\)\(n\)的逆元,即\(n^{-1} \pmod{p}\)
\({n \over m} \equiv n \times m^{-1} \pmod{p}\)
\({1 \over 2} \equiv 1 \times 2^{-1} \equiv 3 \pmod{5}\)
\(2 \times 3 \equiv 1 \pmod{5}\)
\(2^{-1} \equiv 3 \pmod{5}\)
费马小定理:\(m\)是大于\(1\)的整数,那么\(a^m \equiv a \pmod{m}\)
扩展:如果\(p\)是质数,那么\(a^{p-1} \equiv 1 \pmod{p}\)\(a^{p-2} \equiv a^{-1} \pmod{p}\)
如果\(p\)是质数,那么\(1,2,3,...,p-1\)都存在逆元
如果\(m\)是合数,那么\(1,2,3,...,m-1\)不都存在逆元
不存在\(k\)使得\(2 \times k \equiv 1 \pmod{4}\)

posted @ 2021-03-27 08:13  1358id  阅读(105)  评论(0编辑  收藏  举报