1 条题解

  • 0
    @ 2025-8-24 22:21:24

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar cfkk
    一入OI深似海,从此AC是路人

    搬运于2025-08-24 22:21:24,当前版本为作者最后更新于2021-12-11 22:29:46,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这道题可以用哈希来做,因为 n 和 m 的范围比较大,还需要二分和前缀和寻找答案。

    但是输入是是行在前,求哈希是要列在前,需要转换。

    求哈希需要用到 Ascii 码,但是 Ascii 中有很多浪费的元素,所以将 Ascii 的 256 为改成 131 位是容错率最小的。

    所以哈希数组的转换公式为:

    hasi,jhas_{i,j} = hasi,j1has_{i,j-1} × 131+ ci,jc_{i,j}

    与大家不同的是,我用的是单哈希,别人是双哈希。

    #include<bits/stdc++.h>
    using namespace std;
    char c[5005][5005];//原方阵
    int n,m;
    unsigned long long has[5005][5005],data[5005];//防止爆内存
    bool check(int mid)
    {
        for(int i=1;i<=m;i++){data[i]=has[i][n-mid];}//把哈希转换到每一列
        sort(data+1,data+m+1);//从小到大排序
        for(int i=2;i<=m;i++)
        {
            if(data[i]==data[i-1]){return 0;}//排序后如果相邻两个相同,就不是正确答案
        }
        return 1;
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++){cin>>c[i][j];}
        }
        for(int j=1;j<=m;j++)//因为是判断列,所以把列放在前面
        {
            for(int i=n;i>0;i--)
            {
                has[j][n-i+1]=has[j][n-i]*131+c[i][j];//哈希转换
            }
        }
        int l=0,r=n-1;
        while(l<r)//二分
        {
            int mid=(l+r+1)/2;//如果是(l+r)/2会死循环
            if(check(mid)){l=mid;}//判断check
            else{r=mid-1;}
        }
        cout<<l<<endl;
        return 0;
    }
    
    
    • 1

    信息

    ID
    5529
    时间
    1000ms
    内存
    32MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者