【JZOJ6277】【NOIP提高组A】矩阵游戏

题目大意

给出一个\(n*m\)的矩阵,其中\(a_{i,j}=(i-1)*m+j\),现在有\(k\)次操作,每次将一行或一列同乘一个数\(y\),求最终矩阵各数之和。
\(n,m \leq 10^6,k \leq 10^5\)

分析

算是一道思博题?

可以发现各操作的顺序并不影响结果,所以可以考虑先做行操作,再做列操作。

做完行操作以后就很好求每一列之和,然后再把列操作做完。

求每列之和的方法是:先求第一列之和,然后推一推下一列之和多了多少,就能求了。

时间复杂度\(O(n+m+k)\)

Code

#include <cstdio>
#include <cstring>
#define F(i, l, r) for (int i = l; i <= r; ++i)

typedef long long ll;
const int N = 1000007;
const ll P = 1e9 + 7;

int n, m, k, x[N], y[N];
short opt[N];
ll ans, s, s1, fir, las, sum[N], mtp[N], p[N];
char c;

int main()
{
    freopen("game.in", "r", stdin);
    freopen("game.out", "w", stdout);
    scanf("%d%d%d", &n, &m, &k);
    F(i, 1, k)
    {
        scanf(" %c%d%d", &c, &x[i], &y[i]);
        opt[i] = (c == 'R' ? 1 : 0);
    }
    F(i, 1, n) mtp[i] = 1;
    F(i, 1, k) if (opt[i]) mtp[x[i]] = mtp[x[i]] * y[i] % P;
    F(i, 1, n) s = (s + (mtp[i] - 1 + P) % P * (1ll * (i - 1) * m % P + 1) % P) % P, s1 = (s1 + (mtp[i] - 1 + P) % P) % P;
    F(i, 1, m)
    {
        fir = i, las = (i + 1ll * (n - 1) * m % P) % P;
        sum[i] = 1ll * (fir + las) * n % P * 500000004ll % P;
        sum[i] = (sum[i] + s) % P, s = (s + s1) % P;
        p[i] = 1;
    }
    F(i, 1, k) if (!opt[i]) p[x[i]] = p[x[i]] * y[i] % P;
    F(i, 1, m) ans = (ans + p[i] * sum[i] % P) % P;
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zjlcnblogs/p/11305778.html
今日推荐