【CF 1186E】Vus the Cossack and a Field

传送门
好懵啊。。。又是一道没有代码就A不了的题。
首先可以发现,相邻的2个小矩阵的和为n*m。这提供了思路:将这种矩阵拼在一起。
可是我们发现,给的x与y所包含的不一定是偶数个小矩阵甚至有些都没有小矩阵,这就说明我们要分类讨论。

先设r与c为小矩阵组成的矩形的行列数。

抱图链接,谢谢

  1. 绿(完整的小矩形组成的矩阵):发现,只有r与c都为奇数时会多出一个,而且在右下角。则此时ans = r * c / 2 * n * m + 余下矩阵ans。(除2要放前面因为这才与奇偶有关)
  2. 黄:其实前文规律不只对小矩形适用,对其余下的也适用。同理,发现会余下最后一个(奇数)。
  3. 红:无法配对,直接暴力计算。

思考一下如何编码:首先要用前缀和,因为用4个点做下标实在太多了不是吗?

上马吧!

#include<cstdio>
typedef long long ll;
const int N = 1002;
int n, m, q, r, c;
ll sum[N][N];
bool pd(const int x, const int y) {
    return (__builtin_popcount(x) + __builtin_popcount(y)) & 1;
}
ll cal(const int x, const int y, bool f) {
    return f == 0 ? sum[x][y] : x * y - sum[x][y];
}
ll O(const int x, const int y) {
    return cal(x - r * n, y - c * m, pd(r, c));//B
}
ll R(const int x, const int y) {
    ll res = 1ll * c / 2 * (x - r * n) * m;
    if(c & 1)
        res += cal(x - r * n, m, pd(r, c - 1));//A
    return res;
}
ll C(const int x, const int y) {
    ll res = 1ll * r / 2 * n * (y - c * m);
    if(r & 1)
        res += cal(n, y - c * m, pd(r - 1, c));
    return res;
}
ll F(const int x, const int y) {
    ll res = 1ll * r * c / 2 * n * m;
    if((r & 1) && (c & 1))
        res += cal(n, m, pd(r - 1, c - 1));
    return res;
}
ll solve(const int x, const int y) {
    if(x == 0 || y == 0)
        return 0;
    r = (x - 1) / n;
    c = (y - 1) / m;
    return O(x, y) + R(x, y) + C(x, y) + F(x, y);
}
int main() {
    int a, b, c, d;
    char ch;
    scanf("%d %d %d", &n, &m, &q);
    for(int i = 1; i <= n; i ++) {
        scanf("\n");
        for(int j = 1; j <= m; j ++) {
            ch = getchar();
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + ch - '0';
        }
    }
    while(q --) {
        scanf("%d %d %d %d", &a, &b, &c, &d);
        printf("%lld\n", solve(c, d) - solve(c, b - 1) - solve(a - 1, d) + solve(a - 1, b - 1));
    }
    return 0;
}

注:
B:手推发现,cal函数前2个变量表示的是那个多余矩阵的大小(既矩阵从(1,1)开始右下角的坐标)。pd函数和cal函数都是由大佬观察得出的,如果有人会证请一定评论好吗?(无力)pd函数含义:r行c列的矩阵的正或反。那么为什么r行c列矩阵表示红色那一坨呢?因为爱情 好吧其实是推出来的。
A:此函数用于计算行。之前说了,会留下最后一个,又因为m是固定的,r行c列前一个矩阵表示其。

好累啊,终于写完了。

如有错误,请大佬在评论区指出,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值