武汉大学2023年新生程序设计竞赛(同步赛)

题目J

思路:

注意到,行和列的贡献可以分开算,故操作顺序对最终的结果没有影响,可以直接从左到右、从上到下进行放棋子操作,按行按列分别计算即可

时间复杂度

Code:

#include <bits/stdc++.h>

using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
#define int long long
#define ull unsigned long long
#define lowbit(i) ((i)&(-i))
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a;i>=b;i--)

typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 200;

int qpow(int a, int n) {
    int ans = 1;
    while (n) {
        if (n & 1) {
            ans = ans * a % mod;
        }
        a = a * a % mod;
        n >>= 1;
    }
    return ans;
}
signed main() {
    IOS
    int n,m;
    cin>>n>>m;
    vector<vector<char>> a(n+1,vector<char>(m+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int cnt=0;
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='#')
            {
                cnt++;
            }
            else{
                ans+=(cnt)*(cnt+1)*(2*cnt+1)/6;
                cnt=0;
            }
        }
        ans+=(cnt)*(cnt+1)*(2*cnt+1)/6;
    }
    for(int i=1;i<=m;i++)
    {
        int cnt=0;
        for(int j=1;j<=n;j++)
        {
            if(a[j][i]=='#')
            {
                cnt++;
            }
            else{
                ans+=(cnt)*(cnt+1)*(2*cnt+1)/6;
                cnt=0;
            }
        }
        ans+=(cnt)*(cnt+1)*(2*cnt+1)/6;
    }
    cout<<ans<<endl;
    return 0;
}