典型的中国剩余定理题,我用自己写的剩余定理跪掉了
原因是我在套用expand_gcd(a,b,d,x,y)时总是傻乎乎地令d=gcd(a,b)
值得一说的是fzu oj的注册相当的不友好!!!,鼠标要移动到导航栏member上但不要点击才会出现register选项!!!
代码如下:
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 110
#define LL long long
using namespace std;
LL a[MAXN], m[MAXN], n[MAXN];
LL gcd(LL a, LL b) {
return b==0 ? a : gcd(b, a%b);
}
void expand_gcd(LL a, LL b, LL d, LL &x, LL &y) {
if(b == 0) {
d = a;
x = 1;
y = 0;
} else {
expand_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
}
LL chinese_remainder(LL a[], LL n[], LL num) {
LL M = 1;
LL d, x, y;
LL sum = 0;
for(int i=0; i<num; ++i)
M *= n[i];
for(int i=0; i<num; ++i) {
m[i] = M/n[i];
expand_gcd(m[i], n[i], d, x, y);
// cout << "x = " << x << endl;
x = (x%n[i]+n[i])%n[i];//这里的处理很重要,保证x取得的是最小非负整数
// cout << "d = " << d << " x = " << x << endl;
sum = (sum+x*m[i]*a[i]%M)%M;
}
return sum%M;
}
int main(void) {
int T;
while(cin >> T) {
for(int i=0; i<T; ++i) {
cin >> n[i] >> a[i];
}
cout << chinese_remainder(a, n, T) << endl;
}
return 0;
}
发现了一个很有趣的写法,可以依次读入数据,判断当前的ans%a[i]是否等于b[i]
若等于则继续,不等于则一直加前(i-1)个a[i]的乘积直至满足条件,这种贪心的策略也是可行的
代码相当简洁:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 11
#define LL long long
using namespace std;
LL a, b, ans, m, n;
int main(void) {
while(cin >> n) {
cin >> a >> b;
m = a;
ans = b;
for(int i=1; i<n; ++i) {
cin >> a >> b;
while(ans%a != b)
ans += m;
m *= a;
}
cout << ans << endl;
}
return 0;
}