1. 程式人生 > 其它 >AT1278 Counting on a Triangle 題解

AT1278 Counting on a Triangle 題解

題意

一個第 \(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;
}