AtCoder Beginner Contest 058 ABC058 D - 井井井
解説
問題の言い換え
数え上げの典型として、「問われている対象を別のものの数え上げで考える」という方針があります。今回もその例に漏れず、出てくる長方形全てではなく、「長方形の最小単位がそれぞれ何回出てくるかを数え上げる」という方針を取りたくなります。
直線と、とに囲まれた長方形の面積を、登場回数をとすると、求める値は
と言い換えられます。
このままでは、たとえやが適切に前計算できたとしても計算量がになってしまいます。
面積Sの計算
面積は簡単に計算できて、
便宜上、とおくと、
となります。
登場回数Cの数え上げ ~ xとyは独立 ~
登場回数の数え上げですが、ある長方形は直線を側からつ、側からつ選択することに対応することを考えると、側と側は独立に選ぶことになります。
について、番目の区間が含まれるように二直線を選ぶ場合の数はとなります。についても同様です。
便宜上、とおくと、
となります。
シグマの計算
以上でとが立式できたので、答えに入れてみると
よって の前計算で解くことができました。
実装
struct mint { /* 省略 */ }; int main() { ll N, M; cin >> N >> M; vector<ll> x(N), y(M); rep(i,N)cin >> x[i]; rep(i,M)cin >> y[i]; vector<mint> xx(N-1), yy(M-1); rep(i,N-1)xx[i] = x[i+1] - x[i]; rep(i,M-1)yy[i] = y[i+1] - y[i]; vector<mint> a(N-1), b(M-1); rep(i,N-1) a[i] = mint(i+1) * mint(N - i - 1); rep(i,M-1) b[i] = mint(i+1) * mint(M - i - 1); mint sum[] = {0,0}; rep(i,N-1)sum[0] += xx[i] * a[i]; rep(j,M-1)sum[1] += yy[j] * b[j]; mint ans = sum[0] * sum[1]; cout << ans << endl; }