トップページに戻る    次の競技プログラミングの問題へ    前の競技プログラミングの問題へ

ABC-058-D 井井井 / ###

■■■問題■■■

2次元平面上にx軸と平行な直線がm本とy軸と平行な直線がn本引いてあります。
x軸と平行な直線のうち下からi番目は y=yi で表せます。
y軸と平行な直線のうち左からi番目は x=xi で表せます。

この中に存在しているすべての長方形についてその面積を求め、
合計を1000000007で割ったあまりを出力してください。

つまり、1 <= i < j <= n と 1 <= k < l <= m を満たすすべての組 (i,j,k,l) について、
直線 x=xi, x=xj, y=yk, y=yl で囲まれる 長方形の面積を求め、
合計を1000000007で割ったあまりを出力してください。

■■■入力■■■

n m
x1 x2 ・・・ xn
y1 y2 ・・・ ym

●2 <= n,m <= 10万
●-10億 <= x1 < ・・・ < xn <= 10億
●-10億 <= y1 < ・・・ < ym <= 10億
●xi,yi は整数である

■■■出力■■■

長方形の面積の合計を1000000007で割ったあまりを1行に出力せよ。

■■■サンプルケースのイメージ■■■

■入出力例1のイメージ■

この入力を図にすると、以下のようになります。



長方形 A,B, ・・・ ,I それぞれの面積を合計すると60になります。



C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    const long Hou = 1000000007;

    static string InputPattern = "Input1";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("3 3");
            WillReturn.Add("1 3 4");
            WillReturn.Add("1 3 6");
            //60
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("6 5");
            WillReturn.Add("-790013317 -192321079 95834122 418379342 586260100 802780784");
            WillReturn.Add("-253230108 193944314 363756450 712662868 735867677");
            //835067060
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();
        int[] XArr = InputList[1].Split(' ').Select(A => int.Parse(A)).ToArray();
        int[] YArr = InputList[2].Split(' ').Select(A => int.Parse(A)).ToArray();

        long SenbunSumX = DeriveSenbunSum(XArr);
        long SenbunSumY = DeriveSenbunSum(YArr);

        long Answer = SenbunSumX * SenbunSumY;
        Answer %= Hou;
        Console.WriteLine(Answer);
    }

    //座標の配列を引数として、作成可能な線分の長さの総和を返す
    static long DeriveSenbunSum(int[] pArr)
    {
        int UB = pArr.GetUpperBound(0);
        long SenbunSum = 0;
        for (int I = 0; I <= UB; I++) {
            long CurrPos = pArr[I] % Hou;
            int KeisuuMinus = I;
            int KeisuuPlus = UB - I;
            SenbunSum += -CurrPos * KeisuuMinus;
            SenbunSum %= Hou;
            SenbunSum += CurrPos * KeisuuPlus;
            SenbunSum %= Hou;
        }
        return SenbunSum;
    }
}


解説

数直線に点A,B,C,D,Eがあるとし、
任意の2点からなる線分の長さの総合計を求めるとすると、
点Aは、線分の始点となるのが4回、終点となるのが0回
点Bは、線分の始点となるのが3回、終点となるのが1回
点Cは、線分の始点となるのが2回、終点となるのが2回
点Dは、線分の始点となるのが1回、終点となるのが3回
点Eは、線分の始点となるのが0回、終点となるのが4回
ですので、

線分の長さの総合計は、
A*(-4) + B*(-2) + C*0 + D*2 + E*4
で求まります。

そして、積の法則の感覚を使って、
X方向の線分の長さの総合計と
Y方向の線分の長さの総合計を掛け算すれば解となります。