1 条题解
-
0
自动搬运
来自洛谷,原作者为

Great_Influence
**搬运于
2025-08-24 21:36:28,当前版本为作者最后更新于2017-09-26 20:44:06,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
练前缀和的一道好题。
首先可以考虑暴力做法。直接算前缀和就可以了(然而三维前缀和)。然而发现时间复杂度为O(n^6)不能过。于是可以考虑优化。
然后可以发现,如果一个立方体为所求的立方体的话,那么它的最高平面以下的方块数字和与它最低平面-1以下的方块数字和应该是相等的。所以可以考虑记录后快速加减。这样的话只需要枚举平面与高度就可以了。时间复杂度O(n^5)(其实也是勉强卡过去)
代码:
#include<bits/stdc++.h> #include<cctype> #include<algorithm> #include<set> #define For(i,a,b) for(i=(a);i<=(b);++i) #define Forward(i,a,b) for(i=(a);i>=(b);--i) using namespace std; template<typename T>//快读 inline void read(T &x) { T s=0,f=1; char k=getchar(); while(!isdigit(k)&&(k^'-'))k=getchar(); if(!isdigit(k)) { f=-1; k=getchar(); } while(isdigit(k)) { s=s*10+(k^48); k=getchar(); } x=s*f; } const int MAXN=50; int n,m; long long sum[MAXN][MAXN][MAXN];//前缀和(long long可以不开) int C[1000010],clean[100],e;//记录数组与清空数组。不这样清空的话时间复杂度为O(n^4m)根本过不了 int main(void) { read(n); read(m); int i,j,k,x,y,z,ans=0; For(i,1,n) For(j,1,n) For(k,1,n) { read(sum[i][j][k]); sum[i][j][k]%=m; sum[i][j][k]= (sum[i-1][j][k]+sum[i][j-1][k]+sum[i][j][k-1]+sum[i][j][k]-sum[i-1][j-1][k]-sum[i][j-1][k-1]-sum[i-1][j][k-1] +sum[i-1][j-1][k-1]+3*m)%m;//计算前缀和
} For(i,1,n) For(j,1,n) For(x,1,i) For(y,1,j)//枚举平面 { while(e)C[clean[e--]]=0;//清空之前平面的记录情况。 For(k,1,n) { int s=(sum[i][j][k]-sum[x-1][j][k]-sum[i][y-1][k] +sum[x-1][y-1][k]+2*m)%m;//计算方块数字和 if(!C[s])clean[++e]=s;//计入清空数组 ans+=C[s];//加入答案 ++C[s]; } ans+=C[0];//记得直接余0的需要再加上去 } printf("%d\n",ans); return 0; }
- 1
信息
- ID
- 1334
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者