1 条题解

  • 0
    @ 2025-8-24 21:36:28

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 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
    上传者