cogs——1786. 韩信点兵

          1786. 韩信点兵

            ★★★   输入文件:HanXin.in   输出文件:HanXin.out   简单对比
                  时间限制: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<Pi.

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 20
using namespace std;
long long n,s,a[N],m[N],tot,ans,M=1;
long long read()
{
    long long x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    long long r=exgcd(b,a%b,x,y),tmp;
    tmp=x,x=y,y=tmp-a/b*y;
    return r;
}
long long crt()
{
    long long mi=0,sum=0;
    for(int i=1;i<=n;i++)
    {
        long long x,y;
        mi=M/m[i];
        exgcd(mi,m[i],x,y);
        sum=(sum%M+a[i]%M*mi%M*x%M)%M;
    }
    if(sum<0) sum+=M;
    return sum;
}
int main()
{
    freopen("HanXin.in","r",stdin);
    freopen("HanXin.out","w",stdout);
    s=read(),n=read();
    for(int i=1;i<=n;i++)
     m[i]=read(),a[i]=read(),M*=m[i];
    tot=crt();
    while(tot+M<=s) tot+=M;
    ans=s-tot;
    if(tot>s) printf("-1");
    else printf("%lld",ans);
}
时间: 2024-10-13 14:38:14

cogs——1786. 韩信点兵的相关文章

COGS 1786. 韩信点兵

★★★   输入文件:HanXin.in   输出文件:HanXin.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 韩信是中国军事思想“谋战”派代表人物,被后人奉为“兵仙”.“战神”.“王侯将相”韩信一人全任.“国士无双”.“功高无二,略不世出”是楚汉之时人们对其的评价.作为统帅,他率军出陈仓.定三秦.擒魏.破代.灭赵.降燕.伐齐,直至垓下全歼楚军,无一败绩,天下莫敢与之相争. 相传,韩信带兵打仗时,从不直接清点军队人数.有一次,韩信带1500名兵士打仗,战死四

COGS——T 1786. 韩信点兵

http://www.cogs.pro/cogs/problem/problem.php?pid=1786 ★★★   输入文件:HanXin.in   输出文件:HanXin.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 韩信是中国军事思想“谋战”派代表人物,被后人奉为“兵仙”.“战神”.“王侯将相”韩信一人全任.“国士无双”.“功高无二,略不世出”是楚汉之时人们对其的评价.作为统帅,他率军出陈仓.定三秦.擒魏.破代.灭赵.降燕.伐齐,直至垓下全歼楚军,无一败

数学上的一些小技巧韩信点兵的问题

对于韩信点兵的问题,一个数n:n%3=t1;n%5=t2;n%7=t3;如果现在告诉你这三个余数,问你怎么求出来n.只要求最小的一个n就行解法如下: 一.首先对于3来说,因为70能被5和7整除,并且对三取余等于1: 二.对于5来说,因为21能被3和7整除,并且对于5取余等于1 三.对于7来说,因为15能被3和5整除,并且对于7取余等于1. 四.则就是将70*t1+21*t2+15*t3;如果得到的数比105大,那么将这个数减去105:直到小于105: 原理就是: 70=3*n+1;所以70*t1

习题 2-1 位数 2-2 水仙花数 2-3 韩信点兵 2-4倒三角形 2-6 调和级数 2-7近似计算 2-8 子序列的和

2-1 位数 #include<stdio.h> #include<math.h> int main () { int n; for (n=100; n<=999; n++) { if(n == pow(n/100,3) + pow(n/10%10,3) + pow(n%10,3) ) printf("%d\n",n); } system("PAUSE"); return EXIT_SUCCESS; } 2-2 水仙花数 #includ

韩信点兵(中国剩余定理)

中国剩余定理是数论中的一个关于一元线性同余方程组的定理,说明了一元线性同余方程组有解的准则以及求解方法.又称为孙子定理,"韩信点兵""求一术""鬼谷算""隔墙算""剪管术""秦王暗点兵""物不知数"等名称. 例如:物不知数原文: 有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二.问物几何? 宋朝数学家秦九韶对"物不知数"问题作出了完整系统的解

【C】韩信点兵

我姐给我出了一道题,让我去编一个韩信点兵的程序 学了循环结构后,总算编出来了 警告!有大量膜法 1 #include <stdio.h> 2 3 int main() 4 { 5 int A,a; 6 int B,b; 7 int C,c; 8 int D; 9 printf("有一数,除以\n"); 10 11 scanf("%d",&A); 12 printf("余\n"); 13 scanf("%d"

南阳理工--韩信点兵

#include<stdio.h>int main(){  int a,b,c;  int x;  scanf("%d%d%d",&a,&b,&c);  for(x=10;x<=100;x++)  {   if(x%3==a&&x%5==b&&x%7==c)   {    printf("%d\n",x);    break;   }  }  if(x>100)  {   printf(

ACM试题 - 韩信点兵

1. ACM试题题源:http://acm.nyist.net/JudgeOnline/problem.php?pid=34 关于韩信点兵:淮安民间传说着一则故事——“韩信点兵”,其次有成语“韩信点兵,多多益善”.韩信带1500名兵士打仗,战死四五百人,站3人一排,多出2人:站5人一排,多出4人:站7人一排,多出6人.韩信马上说出人数:1049. 2. 解题思路 思路一:可以先求出三组数,这三组数分别是分别用3,5,7除总人数在规定范围内所有的可能数值,然后求得这三组数中相同的那个数即可. 例如

4.韩信点兵:有一个数,用3除余2;用5除余3;用7除余2,求满足条件的最小数

(1)用IF嵌套: #include <iostream>using namespace std; int main(){    int i=100;    int minNum;    while(i>0)    {        if(i%3==2)        {            if(i%5==3)            {                if(i%7==2)                {                    minNum=i;