AT1278 Counting on a Triangle 題解
阿新 • • 發佈:2022-02-11
題意
一個第 \(n\) 行有 \(n\) 個點的矩陣,其規律為每個點的值為每個點橫座標與縱座標的乘積,求第 \(A\) 行到第 \(B\) 行所有點的值的和(包括 \(A\),\(B\) 兩行),結果 \(\mod1000000007\)。
暴力做法
列舉每個數並累加取模即可,顯然,複雜度 \(\Theta(n^2)\) 的暴力會 TLE,因為資料範圍是 \(10^6\)。
優化
仔細觀察這個矩陣,我們可以一行一行考慮,
對於第 \(n\) 行,每個點的座標分別為 \((1,n),(2,n),(3,n)\cdots(n-1,n),(n,n)\),
這些點的值的和為 \(n + 2n + 3n + \cdots + (n-1)n + n^2\)
提取公因數後得 \(n(1 + 2 + 3 + \cdots + n-1 + n)\),
因此問題就轉化為了求這個等差數列的和。
運用我們數學課的知識,對一個等差數列求和,其公式為 \(\frac{n(n+1)}{2}\)。
再回到暴力解法,原來的第二層迴圈就可以替換為等差數列求和,這時就只有一重迴圈了,時間複雜度 \(\Theta(n)\)。
程式碼
分析之後程式碼就很好寫了,注意取模,雖然答案再 int 範圍內,但是在計算過程中可能會超出 int 範圍,所以開 long long 會更保險。
#include<bits/stdc++.h> using namespace std; #define ll long long const int mod = 1000000007; ll a, b, ans; int main() { scanf("%lld%lld", &a, &b); for(ll i = a; i <= b; i++) { ans += (i * (i * (i + 1) / 2) % mod) % mod; ans %= mod; } printf("%lld\n", ans); return 0; }