CJOJ 1272 韩信点兵

来源:互联网 发布:皇太子的王子网络剧 编辑:程序博客网 时间:2024/05/16 10:39

韩信点兵

Description

韩信是中国军事思想“谋战”派代表人物,被后人奉为“兵仙”、“战神”。“王侯将相”韩信一人全任。“国士无双”、“功高无二,略不世出”是楚汉之时人们对其的评价。作为统帅,他率军出陈仓、定三秦、擒魏、破代、灭赵、降燕、伐齐,直至垓下全歼楚军,无一败绩,天下莫敢与之相争。
相传,韩信带兵打仗时,从不直接清点军队人数。有一次,韩信带1500名兵士打仗,战死四五百人。站3人一排,多出2人;站5人一排,多出4人;站7人一排,多出6人。韩信马上说出人数:1049。
这次,刘邦派韩信带兵N人攻打一座重兵驻扎的城市。城市占领了,可汉军也是伤亡惨重。韩信需要知道汉军至少损失了多少兵力,好向刘邦汇报。
已知韩信发出了M次命令,对于第i次命令,他选择一个素数Pi,要求士兵每Pi人站一排,此时最后一排剩下了aiai人。你的任务是帮助韩信求出这种情况下汉军损失兵力的最小值。当然,由于士兵们都很疲惫,他们有可能站错队伍导致韩信得到的数据有误。

Input

第一行两个正整数N,M,分别代表最初的军队人数和韩信的询问次数。
接下来有M行,每行两个非负整数$Piai$,代表韩信选择的素数和此时剩下的人数。
输入保证每个素数各不相同。

Output

输出一行,一个整数。
若有解,输出最小损失人数。若无解,输出-1.

Sample Input

1500 3
3 2
5 4
7 6

Sample Output

31

Hint

对于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;保证所有素数的乘积≤10121012, 0≤ai≤Pi.

Source

数论,欧几里得,中国剩余定理

Solution

注意中国剩余定理求出来的剩下的总人数,如果要损伤的人最少,那么剩下的人应该最多,所以在扩展解系的时候与以往不同

Code

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <map>#include <vector>#include <queue>#define LL long longusing namespace std;LL N;int num, m[20], r[20];inline LL gcd(LL a, LL b) {  return (a % b == 0) ? b : gcd(b, a % b);}inline 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;}inline LL solve() {  LL M = m[1], R = r[1];  for (int i = 2; i <= num; ++i) {    LL d = gcd(M, m[i]), c = r[i] - R;    if (c % d) return -1;    LL x, y;    exgcd(M / d, m[i] / d, x, y);    x = (c / d * x) % (m[i] / d);    R += x * M, M = M / d * m[i];    R %= M;  }  while (R < N) R += M;  if (R - M > 0) R -= M;  return R;}int main(){  freopen("CJOJ1272.in", "r", stdin);  freopen("CJOJ1272.out", "w", stdout);  scanf("%lld %d", &N, &num);  for (int i = 1; i <= num; ++i) scanf("%d %d", &m[i], &r[i]);  LL ans = solve();  if(ans > N || ans == -1) printf("-1\n");  else printf("%lld\n", N - ans);  return 0;}


Summary

判断无解的时候有两种情况,要么剩下的人数比原来的多,要么本来方程就无解

0 0