模拟赛 合唱队形(源于POJ 2891)

【问题描述】

学校要进行合唱比赛了,于是班主任小刘准备给大家排个队形。

他首先尝试排成m1行,发现最后多出来a1个同学;接着他尝试排成m2行,发现最后多出来a2个同学,……,他尝试了n种排队方案,但每次都不能让同学们正好排成mi行。于是小刘寻求同事小明的帮助,以便给同学们排好队形。但小刘来去太匆忙,忘记告诉小明他们班有多少人了。没办法,现在只能根据上述信息求个满足要求的最小的数字来作为人数了。

    虽然小明年轻时是理科生,但是他不愿意去思考这个问题;于是他找到了善于编程的你,希望你能通过编程来解决。

【输入格式】

    第一行为一个整数n,表示小刘尝试了n种排队方案。

    接下来n行,每行有两个整数mi,ai,表示小刘在第i种排队方案中,尝试让同学排成m行,最后多出来ai个同学。

【输出格式】

    每个输出文件只有一个整数,表示最少学生数。如果找不到这样的整数,说明小刘口误了,输出-1。

【输入样例】

    3

    3 1

    5 1

    7 2

 【输出样例】

    16

【数据范围和约定】

    对于40%的测试数据,满足mi≤l00。

    对于l00%的测试数据,满足n≤10,0<ai<mi≤1000。

测试数据保证结果在64位整型存储范围内。

【提示】

    注意语句a=b%c;(a=b mod  c),程序算出的a可能小于0。

题解

exgcd。可以当做一种模板用。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int n,pd;
ll a1,b1,a2,b2,ansx,ansy;
ll gcd(ll a,ll b)
{
	if(b==0) return a;
	else return gcd(b,a%b);
}
void exgcd(ll a,ll b)
{
	if(b==0) {ansx=1; ansy=0; return;}
	else
	   {exgcd(b,a%b);
	    ll t=ansx; ansx=ansy; ansy=t-a/b*ansy;
	   }
}
int main()
{
	ll a,b,c;
	freopen("number.in","r",stdin);
	freopen("number.out","w",stdout);
	scanf("%d",&n);
	pd=0;
	scanf("%I64d%I64d",&a1,&b1);
	for(int i=2;i<=n;i++)
	   {scanf("%I64d%I64d",&a2,&b2);
	    if(pd) continue;
		a=a1; b=a2; c=b2-b1;
		ll t=gcd(a,b);
		if(c%t) {printf("-1\n"); pd=1;}
		else
		   {a/=t; b/=t; c/=t;
			exgcd(a,b);
			ansx=((c*ansx)%b+b)%b;
			b1=b1+a1*ansx;
			a1=a1*b;
		   }
	   }
	if(!pd) printf("%I64d\n",b1);
	return 0;
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值