关于 中国剩余定理 的两道水题练手

15 篇文章 0 订阅

51Nod 1079 中国剩余定理

一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
Input
第1行:1个数N表示后面输入的质数及模的数量。(2 <= N <= 10)
第2 - N + 1行,每行2个数P和M,中间用空格分隔,P是质数,M是K % P的结果。(2 <= P <= 100, 0 <= K < P)
Output
输出符合条件的最小的K。数据中所有K均小于10^9。
Input示例
3
2 1
3 2
5 3
Output示例
23

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>

using namespace std;
#define LL long long
LL a[100],m[100]; int n;
LL M=1;
void EXGCD(LL a,LL b,LL &x,LL &y){
    if(!b){
        x=1; y=0; return ;
    }
    EXGCD(b,a%b,x,y);
    int tmp=x; x=y;
    y=tmp-(a/b)*y;
}
LL CRT(LL a[],LL m[],int n){
    LL ans=0;
    for(int i=1;i<=n;i++){
        LL x,y;
        LL Mi=M/m[i];
        EXGCD(Mi,m[i],x,y);
        ans=(ans+Mi*x*a[i])%M;
    }
    if(ans<0) ans+=M;
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&m[i],&a[i]);
        M*=m[i];
    }
    LL ans=CRT(a,m,n);
    printf("%lld\n",ans);
    return 0;
}

COGS 1786. 韩信点兵

时间限制:1 s 内存限制:256 MB
【题目描述】
韩信是中国军事思想“谋战”派代表人物,被后人奉为“兵仙”、“战神”。“王侯将相”韩信一人全任。“国士无双”、“功高无二,略不世出”是楚汉之时人们对其的评价。作为统帅,他率军出陈仓、定三秦、擒魏、破代、灭赵、降燕、伐齐,直至垓下全歼楚军,无一败绩,天下莫敢与之相争。
相传,韩信带兵打仗时,从不直接清点军队人数。有一次,韩信带1500名兵士打仗,战死四五百人。站3人一排,多出2人;站5人一排,多出4人;站7人一排,多出6人。韩信马上说出人数:1049。
这次,刘邦派韩信带兵N人攻打一座重兵驻扎的城市。城市占领了,可汉军也是伤亡惨重。韩信需要知道汉军至少损失了多少兵力,好向刘邦汇报。
已知韩信发出了M次命令,对于第i次命令,他选择一个素数Pi,要求士兵每Pi人站一排,此时最后一排剩下了ai人。你的任务是帮助韩信求出这种情况下汉军损失兵力的最小值。当然,由于士兵们都很疲惫,他们有可能站错队伍导致韩信得到的数据有误。
【输入格式】
第一行两个正整数N,M,分别代表最初的军队人数和韩信的询问次数。
接下来有M行,每行两个非负整数Pi,ai,代表韩信选择的素数和此时剩下的人数。
输入保证每个素数各不相同。
【输出格式】
输出一行,一个整数。
若有解,输出最小损失人数。若无解,输出-1.
【样例输入】
1500 3
3 2
5 4
7 6
【样例输出】
31
【数据范围】
对于30%的数据,1≤N≤1,000,000,1≤M≤4;
对于50%的数据,1≤N≤100,000,000,1≤M≤8;
对于100%的数据,1≤N≤1,000,000,000,000,1≤M≤10;保证所有素数的乘积≤1012,0≤ai

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
LL n,T,a[15],m[15],M=1;
void EXGCD(LL a,LL b,LL &x,LL &y){
    if(!b){ x=1;y=0;return; }
    EXGCD(b,a%b,x,y);
    int tmp=x;x=y;
    y=tmp-(a/b)*y;
}
LL CRT(){
    LL ans=0;
    for(int i=1;i<=T;i++){
        LL x,y,Mi=M/m[i];
        EXGCD(Mi,m[i],x,y);
        ans=(ans+Mi*x*a[i])%M;
    }
    return ans;
}
int main(){
    //freopen("HanXin.in","r",stdin);
    //freopen("HanXin.out","w",stdout);
    scanf("%lld%lld",&n,&T);
    for(int i=1;i<=T;i++){
        scanf("%lld%lld",&m[i],&a[i]);
        M*=m[i];
    }
    LL ans=CRT();
    if(ans>n){
        printf("-1");
        return 0;
    }
    while(ans+M<=n) ans+=M;
    printf("%lld\n",n-ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值