其他分享
首页 > 其他分享> > 习题:与或和(单调栈)

习题:与或和(单调栈)

作者:互联网

题目

传送门

思路

因为与位运算有关

所以第一点可以想到是算包含每一位的有哪些矩阵

有了这一个思路之后

问题可以分为两个子问题

问题1:如何求&

对于一个矩阵,如果我们假设这个矩阵的&值的二进制第k位为1

那么其中的每一个数的二进制的第k位都为1

有了这个之后,直接单调栈怼上去就行了

问题2:如何求|

如果采用和求&一样的方式去思考

我们发现如果这个矩阵的|值得二进制第k位为1

那么矩阵中至少有一个数的二进制第k位为1

但是我们发现这个东西不好直接求

但是你可以用全部的矩阵数量减去不合条件的矩阵

也就是说,

减去的不合条件的矩阵其实就是&值的二进制的第k位为0的矩阵

一样的单调栈怼上去就行了

代码

#include<iostream>
#include<cstdio>
using namespace std;
const int mod=1e9+7;
long long n;
long long s_top;
long long st[1005];
long long h[1005];
long long w[1005];
long long a[1005][1005];
long long ans_and;
long long ans_or;
long long solve_sum(long long limt)
{
    return limt*(limt+1)/2;
}
long long solve(int bj)
{
    long long tot=0;
    for(int i=1;i<=n;i++)
        h[i]=0;     
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if((a[i][j]&1)==bj)
                h[j]++;
            else
                h[j]=0; 
            if(h[j]>st[s_top])
            {
                st[++s_top]=h[j];
                w[s_top]=1;
            }
            else
            {
                long long wid=0;
                while(st[s_top]>h[j])
                {
                    wid+=w[s_top];
                    tot=(tot+(st[s_top]-max(st[s_top-1],h[j]))*solve_sum(wid))%mod;
                    s_top--;    
                }
                st[++s_top]=h[j];
                w[s_top]=wid+1;
            }
        }
        long long wid=0;
        while(s_top)
        {
            wid+=w[s_top];
            tot=(tot+(st[s_top]-st[s_top-1])*solve_sum(wid))%mod;
            s_top--;
        }
    }
    return tot;
}
void dfs(int dep)
{
    if(dep==32)
        return;         
    ans_and=(ans_and+solve(1)*(1ll<<dep))%mod;
    ans_or=(ans_or+(solve_sum(n)*solve_sum(n)%mod-solve(0))*(1ll<<dep))%mod;
//cout<<solve(1)<<' '<<solve(0)<<'\n';
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            a[i][j]>>=1;
    dfs(dep+1);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            cin>>a[i][j];
    dfs(0);
    cout<<(ans_and+mod)%mod<<' '<<(ans_or+mod)%mod;
    return 0;
}

标签:wid,top,矩阵,long,st,tot,习题,单调
来源: https://www.cnblogs.com/loney-s/p/12038988.html