矩陣游戲(game)
——九校聯考24OI__D1T1
問題描述
LZK發明一個矩陣游戲,大家一起來玩玩吧,有一個N行M列的矩陣。第一行的數字是1,2,…M,第二行的數字是M+1,M+2…2*M,以此類推,第N行的數字是(N-1)*M+1,(N-1)*M+2…N*M。
例如,N=3,M=4的矩陣是這樣的:
1 2 3 4
5 6 7 8
9 10 11 12
對於身為智慧之神的LZK來說,這個矩陣過於無趣.於是他決定改造這個矩陣,改造會進行K次,每次改造會將矩陣的某一行或某一列乘上一個數字,你的任務是計算最終這個矩陣內所有數字的和,輸出答案對109+7取模。
輸入
第一行包含三個正整數N、M、K,表示矩陣的大小與改造次數。接下來的行,每行會是如下兩種形式之一:
R X Y,表示將矩陣的第X(1 ≤ X ≤ N)行變為原來的Y(\(0\) ≤ Y ≤\(10^9\))倍.
S X Y,表示將矩陣的第X(1 ≤ X ≤ M)列變為原來的Y(\(0\) ≤ Y ≤\(10^9\))倍.
輸出
輸出一行一個整數,表示最終矩陣內所有元素的和對\(10^9+7\)取模的結果。
輸入輸出樣例
樣例1
input
3 4 4
R 2 4
S 4 1
R 3 2
R 2 0
output
94
樣例2
input
2 4 4
S 2 0
S 2 3
R 1 5
S 1 3
output
80
樣例一的解釋:操作結束之后矩陣會變成這樣:
1 2 3 4
0 0 0 0
18 20 22 24
數據范圍
40%的數據滿足:1≤N,M≤1000;
80%的數據滿足:1≤N,M≤1000000,1 ≤ K ≤1000;
100%的數據滿足:1≤N,M≤1000000,1 ≤ K ≤100000。
解析
這道題看似是什么數據結構,其實就是數學題。
每一個行都是等差數列(列也是),求出每一行數字的和s[i]。每一次橫行的乘法操作就是重構一下通項公式,每一次縱列的乘法操作就是改變每一個數列中的一項,至於每一行增加了多少,就用通項求那個數是多少,再求增加量,加到s[i]里。
別忘了開longlong,取模,好多同學都忘了這個。
代碼
#include <bits/stdc++.h>
using namespace std;
int N,M,K;
const int MOD = (1e9) + 7;
int R[1000005];
int sumR;
int C[1000005];
int S;
int rez;
int element(int i,int j){
return (1LL * (i - 1) * M + j) % MOD;
}
int main()
{
// freopen("game.in","r",stdin);
// freopen("game.out","w",stdout);
for(int i = 1;i <= 1000000;i++){
R[i] = C[i] = 1;
}
cin >> N >> M >> K;
for(int i = 1;i <= K;i++){
char c;
int x,y;
cin >> c >> x >> y;
if(c == 'R'){
R[x] = 1LL * R[x] * y % MOD;
}
else {
C[x] = 1LL * C[x] * y % MOD;
}
}
for(int i = 1;i <= N;i++){
S = (1LL * S + 1LL * element(i,1) * R[i]) % MOD;
sumR += R[i];
if(sumR >= MOD){
sumR -= MOD;
}
}
for(int i = 1;i <= M;i++){
rez = (1LL * rez + 1LL * S * C[i]) % MOD;
if(rez >= MOD){
rez -= MOD;
}
S += sumR;
if(S >= MOD){
S -= MOD;
}
}
cout << rez<<endl;
return 0;
}