この問題では主に数学的思考を問います。
問題の条件からsantarate君からもnumDeer君からもプレゼントの個数を変更することが可能なため、単に を選んで操作をすればよいです。
まず 種類のときを考えてみます。この場合いかなる個数であっても 回の操作で可能です。すなわち として選ぶことで必ず等しくできます。
種類のとき、例えば の場合は を選び、 に を 回だけ足し、 に 回だけ足すことで等しくできます。また でも達成させることも可能ですが、その場合は合計で 回の操作のため最小値とはなりません。
また 以外ではどんな操作をしようと絶対に がともに等しくなることはありません。これは各個数を で割ったあまりを考えることで示すことができます。
ここで がともに等しくなる を考えると、 と に を 回足すと等しくなるもの、すなわち の正の公約数を に選べばよいです。その中で操作回数を最小化するためには を最大にすることが必要十分なので、 は最大公約数を選ぶことが適切です。
以上から 種類のとき、 は の最大公約数を選べばよいことがわかります。そしてそれぞれの個数に足すべき回数はちょうど を で割った商 に等しい (最大公約数の性質よりあまりは であるから、必ず整数になるため) ので、求める答えは となります。
実装方法によりますが、一般に の最大公約数を求めるアルゴリズム※は で実装できるので、全体で で、この問題を解くことができます。ただし となる が 個あるとき、 はそれらを除いた 個の数値の最大公約数を選ばなくてはならないことに注意してください。
解答例(C++)は以下のようになります。
xxxxxxxxxx
//[0,n)
//[a,b]
using namespace std;
using ll = long long;
using ull = unsigned long long;
using P = pair<ll,ll>;
using pq = priority_queue<ll,vector<ll>,greater<ll>>;
const ll inf = 8e18;
const int iinf = (int)1e9;
const int mod9 = 998244353;
const int mod1 = 1000000007;
struct Edge { int to; ll cost; int from; };
bool compe(const Edge &e,const Edge &e2){ return e.cost < e2.cost; }
using Graph = vector<vector<int>>;
using SGraph = vector<set<ll>>;
template <typename T>
ll siz(T& a){return (ll)a.size();}
long long gcd(long long x,long long y){
if(x*y == 0) return (x == 0 ? y : (y == 0 ? x : 0));
if(x < y) swap(x,y);
return (x%y == 0 ? y : gcd(y,x%y));
}
int main(void){
int n; cin >> n;
vector<int> A(n),B(n);
rep(i,n) cin >> A[i];
rep(i,n) cin >> B[i];
int g = 0;
rep(i,n){
if(A[i] != B[i]){
if(g == 0) g = abs(A[i]-B[i]);
else g = gcd(abs(A[i]-B[i]),g);
}
}
ll ans = 0;
if(g != 0) rep(i,n) ans += abs(A[i]-B[i])/g;
cout << ans;
}
※このアルゴリズムはユークリッドの互除法と呼ばれるものです。詳細はここでは省略しますが、ぜひ調べてみるといいと思われます。
解答例を修正しました。前の解答例ではafter_contest-01,02でREとなります。