待:搞懂裏面的數論知識&動歸的方法
數論:互質數的最大不能組合數
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
int a, b;
cin >> a >> b;
cout << a*b - a - b;
return 0;
}
// 數論知識:互質數的最大不能組合數上界是lcm(a, b),互質所以即a*b
// gcd(a, b) = 1 => lcm(a, b) = a * b
// because gcd(a, b) * lcm(a, b) = a * b
// 運行超時 得分66,最後一組測試數據 257 191 在我電腦上要跑2.5秒
// 強行優化,多加break,從後往前找,一遇到第一個無法組合的數就是它了
#include <iostream>
#include <cstring> //memset
using namespace std;
#define D(x) cout<<#x<<"="<<x<<endl;
bool x[100000];
int re;
void judge(int a, int b) { //判斷一個數能否由a,b兩個數組合
int lcm = a * b;
int num;
// for (num = 1; num <= lcm; ++num) {
for (num = lcm; num >= a; --num) {
for (int i = 0; i <= num / a; ++i) {//a最大個數
for (int j = 0; j <= num / b; ++j) { //b最大個數
if (i * a + j * b == num) {
x[num] = true;
break;
}
}
if (x[num] == true)
break;
}
if (x[num] == false)
break;
}
/*
for (int i = 0; i < a * b; ++i)
{
cout << i << '\t';
}
cout << endl;
for (int i = 0; i < a * b; ++i)
{
cout << x[i] << '\t';
}
*/
//直接找最後的false
re = num;
/*節約時間都可以不用了
for (int i = lcm - 1; i > 1; --i)
if (x[i] == 0) {
re = i;
break;
}
*/
}
int main(int argc, char *argv[]) {
ios::sync_with_stdio(false);
int a, b;
cin >> a >> b;
// memset(x, false, sizeof(x));
judge(a, b);
cout << re;
return 0;
}
// ???直接按順序填,然後從後往前找,要多快有多快
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
int a, b;
cin >> a >> b;
bool x[100000];
for (int i = 0; i <= b; i++) {
for (int j = 0; j <= a; j++) {
x[i * a + b * j] = true;
}
}
for (int i = a * b - 1; i > 1; --i)
if (x[i] == 0) {
cout << i;
break;
}
return 0;
}