zoukankan      html  css  js  c++  java
  • 【luogu P1495】【模板】中国剩余定理(CRT)/曹冲养猪(数论)

    【模板】中国剩余定理(CRT)/曹冲养猪

    题目链接:luogu P1495

    题目大意

    给你一些条件,要你找最小的 x,使得满足它被一些数取模的答案是要求的数。
    且模数相互都是互质的。
    在这里插入图片描述

    思路

    我们考虑我们先让每个式子单独找数满足,这个很好找,我们可以找到 (x_1,x_2,...x_n)
    那你考虑搞 (x_1+x_2),看他能不能同时满足两个式子。
    那你要想,那你为了不破坏余数,那你 (x_2) 要是 (a_1) 的倍数,(x_1) 要是 (a_2) 的倍数。

    那你以此类推,变成所有的加起来,那就是要 (x_1)(a_2,a_3,...,a_n) 的倍数,(x_2)(a_1,a_3,...,a_n) 的倍数,.……。
    这个很好找,就先搞出所有 (a) 的最小公倍数,然后除去 (a_i) 就行。

    那接着你 (x_i) 还要满足模 (a_i)(b_i),那这一步要怎么处理呢?
    那你要求 ( ext{LCM} imes mequiv b_i(mod a_i))
    不如先求 ( ext{LCM} imes mequiv 1(mod a_i)),然后再拿结果乘 (b_i)
    然后不难看出 (m) 就是 ( ext{LCM}) 关于 (a_i) 的逆元。

    那你就求得了 (x_1,x_2,...,x_n)
    加起来就是一个解了。

    但是我们要求最小解,那我们考虑通解。
    那模 (a_i) 的余数什么时候回循环一次呢?(完全匹配的那种)
    不难想到是 ( ext{lcm}{a_i}) 个循环一次。
    那就把答案模 (LCM) 就可以了。

    代码

    #include<cstdio>
    #define ll long long
    
    using namespace std;
    
    int n;
    ll a[11], b[11], LCM, X;
    
    ll gcd(ll x, ll y) {
    	if (!y) return x;
    	return gcd(y, x % y);
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y) {//exgcd 求逆元
    	if (!b) {
    		x = 1;
    		y = 0;
    		return a;
    	}
    	
    	ll re = exgcd(b, a % b, y, x);
    	y -= x * (a / b);
    	return re;
    }
    
    int main() {
    	scanf("%d", &n);
    	LCM = 1;
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld %lld", &a[i], &b[i]);
    		LCM = LCM * a[i] / gcd(LCM, a[i]);//求积
    	}
    	
    	for (int i = 1; i <= n; i++) {
    		ll mi = LCM / a[i];
    		ll x = 0, y = 0;
    		exgcd(mi, a[i], x, y);
    		X += b[i] * mi * ((x % a[i] + a[i]) % a[i]);//注意 x 有可能是负数
    	}
    	
    	printf("%lld", X % LCM);
    	
    	return 0;
    }
    
  • 相关阅读:
    Javascript的this用法
    angularjs学习笔记--1.入门
    git的简单应用
    转:Netty服务器线程模型概览
    Netty 4.0 中文文档
    转:腾讯CKV海量分布式存储系统
    转Redis性能测试
    maven assemby 打包问题
    转发:TCP
    转:HBase Server启动过程
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/luogu_P1495.html
Copyright © 2011-2022 走看看