7月份的机房内模拟考,虽然题不是非常难,但是考得也不太好呢.....
T1 入阵曲
给你一个矩阵和一个常数k,问你有多少个子矩阵的和是k的倍数
数据范围:矩阵长宽不超过400,k<=1e6
我们可以首先想到n^4的做法,先记录二维的前缀和,然后枚举矩形的端点坐标,然后枚举其长和宽,这样可以拿到60分,再加上有15分特殊数据,可以靠暴力拿到75分以上
然后我们可以大概猜到正解是n^2logn或者是n^3,由于矩阵二分起来很不方便,我们就考虑n^3的做法
我们注意到,因为要是k的倍数,所以说只要模k为0的子矩阵就满足要求,因此我们只需要在前缀和中存下子矩阵的和对k的模数即可,我们又可以注意到,如果有一个矩阵和一个大矩阵模k意义下同余,则说明大矩阵减去小矩阵一定是k的倍数,如下图
于是我们只需要枚举起点坐标和长度或者宽度,然后用一个桶来存每一个子矩阵取余过后的数的数量,就可以n^3(其实是n*m^2或者m*n^2)处理这个问题了
代码实现如下
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
const int MAXN=405;
typedef long long ll;
ll ans;
int n,m,k;
int a[MAXN][MAXN];
ll s[MAXN][MAXN];
ll b[MAXN];
int t[1000005];
int vis[1000005],cnt;
int v[MAXN];
int vnum;
void work(int x,int y)
{
cnt++;
vnum