1 条题解

  • 0
    @ 2025-8-24 21:25:44

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar vectorwyx
    打 OI 就像心跳一样自然,退役就像去世一样必然。

    搬运于2025-08-24 21:25:43,当前版本为作者最后更新于2019-11-29 13:21:42,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    蒟蒻不会 CRT,但我们可以使用枚举来切掉这道水题,因此只需要小学五年级的水平

    如何枚举?如果只有两组同余式,求解最直接的思路就是从小到大枚举满足其中一个同余式的所有数直到找到满足另一个同余式的。更具体地,从余数出发,不断加上该同余式所对应的模数,当累加的结果满足另一个同余式时即为我们所求的最小值。

    比如说样例中的3 1 5 1,满足第一个同余式的最小数为 11,然后不断加 33,加五次后得到数 1616,满足第二个同余式,答案即为 1616。这一过程用循环就可以实现。


    得到了两组同余式的解法,我们推广一下即可,nn 组同余式可从前往后,每次取前一次得到的最小数与本同余式进行运算,循环 n1n-1 次便可得出答案。

    比如,对于题目中给出的样例:

    3
    3 1
    5 1
    7 2
    

    首先取前两个同余式,根据上文所述的过程得到满足前两组同余式的最小值为 1616,再在这个最小值的基础上引入第三个同余式,每次增加 3355 的最小公倍数 1515,由于 1616 已经满足第三个同余式,不需要累加。得到答案为 1616

    复杂度至多是 O(ai)O(\sum a_i),即模数之和,完全可过。


    ok,你们最期待的代码来了:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct pig{
    	int a1,b1;
    }a[11];//定义结构体存储a与b
    int gcd(int x,int y){//公约数函数,用来求每一次循环累加的值
    	if(x%y==0) return y;
    	else return gcd(y,x%y);
    }
    int main(){
    	long long n,ans,sum=1;//数据较大用longlong
    	cin>>n;
    	for(int i=1;i<=n;++i){
    		cin>>a[i].a1>>a[i].b1;
    	}
    	ans=a[1].b1;//初始化最小值
    	for(int i=1;i<n;++i){//开始循环
    		sum=sum*a[i].a1/gcd(sum,a[i].a1);//sum为累加的值
    		while(ans%a[i+1].a1!=a[i+1].b1){//循环条件
    			ans+=sum;
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    
    

    祝愿大家 AC,RP++。

    • 1

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

    信息

    ID
    488
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者