「NOIP模拟赛」合唱队形
「问题描述」
学校要进行合唱比赛了,于是班主任小刘准备给大家排个队形。
他首先尝试排成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。
题解
线性同余方程
参见poj2891
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include<cstdio> #include<iostream> #define ll long long using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x*=10;x+=ch-'0';ch=getchar();} return x*f; } int k; ll a1,b1,a2,b2; inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} void exgcd(ll a,ll b,ll &x,ll &y) { if(b==0){x=1;y=0;return;} exgcd(b,a%b,x,y); ll t=x;x=y;y=t-a/b*y; } int main() { //freopen("number.in","r",stdin); //freopen("number.out","w",stdout); k=read(); a1=read();b1=read(); ll a,b,c,x,y; for(int i=1;i<k;i++) { a2=read();b2=read(); a=a1;b=a2;c=b2-b1; ll t=gcd(a,b); if(c%t){printf("-1\n");return 0;} else { a/=t;b/=t;c/=t; exgcd(a,b,x,y); x=((c*x)%b+b)%b; b1=b1+a1*x; a1=a1*b; } } printf("%lld\n",b1); return 0; } |
Subscribe