题目传送门
B题:
扩展欧几里得算法,相当于一个同余方程 (m - n) x = (y - x) (mod l) (m > n) 转换成二元一次方程,用扩展欧几里得求解即可;
第一次写,错了,很多地方比如 (y - x) 写成 x- y 还有就是扩展欧几里得函数写的时候写成了这样
long long gcd_ex (long long a, long long b, long long& x, long long& y)
{
if(b == 0){x = 1, y = 0; return a;}
return d = gcd_ex(b, a%b, y, x);
y = y - a / b * x;
}
这样直接返回了gcd 并没有计算出 x, y 的值;
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long gcd_ex (long long a, long long b, long long &x, long long &y);
int main()
{
long long x, y, m, n, l;
while(cin >> x >> y >> m >> n >> l){
if(m == n){
printf("Impossible\n");
continue;
}
if(m < n){
swap(m, n);
swap(x, y);
}
long long a = m - n;
long long c = y - x;
//cout << c << endl;
c = c > 0 ? c : c + l;
//cout << a <<" "<< l << endl;
long long tx, ty;
long long gcd = gcd_ex(a, l, tx, ty);
//cout << tx << " " << ty << endl;
if(c%gcd){printf("Impossible\n"); continue;}
long long mod = l / gcd;
//cout << tx << endl;
tx *= c / gcd;
tx = (tx % mod + mod) % mod;
cout << tx << endl;
}
return 0;
}
long long gcd_ex (long long a, long long b, long long& x, long long& y)
{
if(b == 0){x = 1, y = 0; return a;}
//cout <<"*" << endl;
long long d = gcd_ex(b, a%b, y, x);
y = y - a / b * x;
return d;
//cout << x << " "<< y << endl;
}
A 题
直接水过,刚开始WA了一发,是因为结果的范围应该在[g , nmax + 1] ,我按[g , nmax] 算的。代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MaxN = 1000000;
bool use[MaxN];
const int MaxG = 300 + 5;
int a[MaxG];
int main()
{
int T;
scanf("%d", &T);
while(T--){
int g, nmax = 0;
scanf("%d", &g);
for(int i=0; i<g; ++i){
scanf("%d", &a[i]);
if(a[i] > nmax) nmax = a[i];
}
for(int i=g; i<=nmax + 1; ++i){
memset(use, 0, i);
int temp;
//cout << i << endl;
bool flag = true;
for(int j=0; j<g; ++j){
temp = a[j] % i;
//cout << a[j] << " " << temp << " " << use[temp] << endl;
if(use[temp]){flag = false; break;}
else use[temp] = true;
}
if(flag) {printf("%d\n", i); break;}
}
}
return 0;
}
D 题
同余方程组求解,用逐一合并发, 注意一点就是题目要求“For each case output the least positive integer X ” 所以,如果最后结果为 0, 那么应该输出模。代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll MaxN = 9;
ll b[MaxN];
ll m[MaxN];
int n;
ll gcd_ex(ll a, ll b, ll& x, ll& y)
{
if(b == 0) {x = 1; y = 0; return a;}
ll d = gcd_ex(b, a%b, y, x);
y = y - a / b * x;
return d;
}
int main()
{
int T, tt=0;
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(ll i=0; i<n; ++i)
cin >> m[i];
for(ll i=0; i<n; ++i)
cin >> b[i];
bool flag = true;
ll x, y;
for(ll i=1; i<n; ++i){
ll gcd = gcd_ex (m[i - 1], m[i], x, y);
ll d = b[i-1] - b[i];
if(d % gcd) {flag = false; break;}
x *= d / gcd;
//cout << gcd << " " << d << " " << x << endl;
m[i] = m[i - 1] / gcd * m[i];
b[i] = b[i-1] - x * m[i-1];
b[i] = (b[i] % m[i] + m[i]) % m[i];
}
printf("Case %d: ", ++tt);
if(flag) {
if(b[n - 1]){
cout << b[n - 1] << endl;
}
else cout << m[n - 1] << endl;
}
else printf("-1\n");
}
return 0;
}
E题:
直接用中国剩余定理求解,这道题因为输出格式问题WA了一发,代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int b[3], day;
const int m[3] = {23, 28, 33};
int gcd_ex(int a, int b, int& x, int& y)
{
if(b == 0){x = 1, y = 0; return a;}
int d = gcd_ex(b, a%b, y, x);
y = y - a / b * x;
return d;
}
int main()
{
int tt = 0;
while(~scanf("%d%d%d%d", &b[0], &b[1], &b[2], &day) && b[0]>-1){
b[0] %= 23, b[1] %= 28, b[2] %= 33;
int M = 28 * 33 * 23, ans = 0;
for(int i=0; i<3; ++i){
int tm = M / m[i];
int x, y;
gcd_ex(tm, m[i], x, y);
x = (x % m[i] + m[i]) % m[i];
ans += b[i] * x * tm;
}
ans = (ans % M + M) % M;
ans -= day;
if(ans <= 0) ans += M;
printf("Case %d: the next triple peak occurs in %d days.\n", ++tt, ans);
}
return 0;
}
F题:
这道题 n = mi - a(mod mi) 可以转化成 n + a = 0 (mod mi) 然后就转化成求最小公倍数的问题了 T^^T代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int MaxN = 13;
ll m[MaxN];
int n, a;
ll gcd(ll a, ll b)
{
if(b == 0) {return a;}
return (gcd(b, a%b));
}
int main()
{
while(~scanf("%d%d", &n ,&a) && n){
for(int i=0; i<n; ++i){
scanf("%I64d", &m[i]);
}
//bool flag = true;
ll ans = 1;
for(ll i=0; i<n; ++i){
ans = ans / gcd(ans, m[i]) * m[i];
}
printf("%I64d\n", ans - a);
/*if(flag) {
if(b[n - 1]){
cout << b[n - 1] << endl;
}
else cout << m[n - 1] << endl;
}
else printf("-1\n");
*/
}
return 0;
}