题解:UVA13291 Frosting on the Cake

题意

给定一个 \(n \times n\) 的网格蛋糕,每个格子 \((i, j)\) 的面积是 \(A_j \times B_i\)。每个格子的颜色由 \((i + j) \bmod 3\) 决定(\(0\): 黄色,\(1\): 粉色,\(2\): 白色)。

要求分别计算三种颜色所覆盖的总面积。

思路

暴力做法是遍历所有格子,时间复杂度为 \(O(n^2)\),当 \(n = 10^5\) 时不可接受。

我们观察到颜色只与 \((i + j) \bmod 3\) 有关,因此可以按 \(i \bmod 3\)\(j \bmod 3\) 对数组进行分组求和。

定义:

  • sumA[r] 表示所有满足 \(j \equiv r \pmod{3}\)\(A_j\) 之和;
  • sumB[r] 表示所有满足 \(i \equiv r \pmod{3}\)\(B_i\) 之和。

那么对于颜色 \(k\)(即 \((i + j) \bmod 3 = k\)),其总面积为:

\[S_k = \sum_{(r_i + r_j) \bmod 3 = k} \text{sumB}[r_i] \cdot \text{sumA}[r_j] \]

只需枚举所有可能的 \((r_i, r_j)\) 组合即可在 \(O(1)\) 时间内完成统计。

代码

# include <bits/stdc++.h>
using namespace std;
long long n , a[100010] , b[100010] , ans[3] , suma[3] , sumb[3];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    while(cin >> n)
    {
        memset(ans , 0 , sizeof ans);
        memset(suma , 0 , sizeof suma);
        memset(sumb , 0 , sizeof sumb);
        for(int i = 1 ; i <= n ; i ++) cin >> a[i];
        for(int i = 1 ; i <= n ; i ++) cin >> b[i];
        for(int i = 1 ; i <= n ; i ++) suma[i % 3] += a[i];
        for(int i = 1 ; i <= n ; i ++) sumb[i % 3] += b[i];
        for(int i = 0 ; i < 3 ; i ++)
            for(int j = 0 ; j < 3 ; j ++)
                ans[(i + j) % 3] += sumb[i] * suma[j];
        cout << ans[0] << " " << ans[1] << " " << ans[2] << "\n";
    }
    return 0;
}

最后说一句:多测不清空,爆零两行泪。

posted @ 2025-08-18 12:50  zhangyimin12345  阅读(13)  评论(0)    收藏  举报