[GXOI / GZOI2019] and the or [monotonous stack]

Perhaps a better reading experience

\(\mathcal{Description}\)

Gives a \ (n \ times n \) , the element is a natural number of the matrix.
This matrix has many sub-matrix, defining a set of all of its sub-matrix formed is \ (S \) .
For a matrix \ (K \) , the definition of \ (f (k) \) of \ (K \) in all elements \ (the aND \) values (bitwise aND).
for a matrix \ (K \) , defined \ (g (k) \) of \ (K \) in all elements \ (oR \) values (bitwise oR).
requesting all sub-matrix \ (f (k) \) the sum of all sub-matrices \ (g (k ) \) sum, i.e., \ (\ begin {aligned} \ sum_ {k \ in S} f (k) \ end {aligned} \) and \ (\ begin {aligned} \ sum_ {k \ in S} g (k) \ end {aligned}
\) to be large because the answer, the answer needs to output only (1e9 + 7 \) \ modulo results.

\ (n \ leq1000, \) in the size of each element of the matrix (int \) \ in the range of

\(\mathcal{Solution}\)

One topic for arithmetic operations, the method of calculating the contribution of the first consideration is in bits contributions
because contributions are a bit of other bits will not be affected, while the overall computing because of the particularity bit computing, or will be taken into account by bit computing

We enumerate every \ (k \) , then the matrix into \ (0/1 \) matrix, where \ (0 \) element represents the original matrix element represents the enumeration to the binary is \ (0 \) , as \ (1 \) , compared with \ (1 \)
consider the \ (0/1 \) matrix in the number of sub-matrix contribution will be calculated, and finally put this number multiplied by \ (2 ^ k \)

For the operation, which is to ask how many full \ (1 \) matrix
for or operation, which is to ask how many have \ (1 \) matrix

And the arithmetic operation can actually be interchangeable or
full \ (1 \) Matrix Matrix = number of all - at \ (0 \) Matrices
have \ (1 \) Matrix Matrix = number of all - Full \ (0 \) matrix number

Set \ (All \) of \ (n \ times n \) all submatrices included in the matrix
is clearly \ (all = (\ frac { n (n + 1)} {2}) ^ 2 \)

After considering how to calculate the number of matrix satisfying the conditions

\ (55 \) Decomposition \ (O (log_2n \ cdot n
^ 3) \) considerations enumerated boundary matrix, the lower boundary
we count the number of requirements to meet in such a matrix
with a\ (1 \)matrix clearly easy to do
considering the enumeration to a matrix leftmost\ (1 \)appears location
so you can do not leak all computing
obviously, as long as this has included\ (1 \)of one, all matrices are in the current scope legal
attention and not on a\ (1 \)that is repeated column

With \ ([i] sum [j ] \) represents \ (J \) column to \ (I \) positions the total number \ (1 \)
long \ (SUM [lower border] [current column] -sum [a boundary -1] [current column]> 0 \) to illustrate this listed \ (1 \)
other very simple, particularly over it while looking at the code

\ (100 \) Decomposition \ (O (log_2n \ cdot n ^ 2) \)

Enumeration considered the lower boundary of the matrix
is calculated full \ (1 \) matrix
with \ (f [i] [j ] \) represents \ (J \) column from \ (I \) began up how many consecutive \ (1 \)
and where an enumeration, and with \ (cnt \) number will increase each matrix representation
with monotonous stack to maintain it

\(\mathcal{Code}\)

\ (55 \) minutes
trying their luck cards often Edition

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年09月10日 星期二 14时17分44秒
*******************************/
#include <cstdio>
#include <fstream>
#include <algorithm>
#define rint register int
using namespace std;
const int maxn = 1003;
const int mod = 1000000007;
//{{{cin
struct IO{
    template<typename T>
    IO & operator>>(T&res){
        res=0;
        bool flag=false;
        char ch;
        while((ch=getchar())>'9'||ch<'0')   flag|=ch=='-';
        while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
        if (flag)   res=~res+1;
        return *this;
    }
}cin;
//}}}
int n,mx,all,ans1,ans2;
int lt[maxn],up[maxn];
int a[maxn][maxn],sum[maxn][maxn];
bool hav[maxn];
bool b[maxn][maxn];
//{{{calc
inline int calc (int mi,bool opt)
{
    int res=0;
    for (rint i=1;i<=n;++i)
        for (int j=1;j<=n;++j){
            b[i][j]=(a[i][j]&mi);
            b[i][j]^=opt;
            sum[i][j]=sum[i-1][j]+b[i][j];
        }
    for (rint i=1;i<=n;++i)//上边界
        for (rint j=i;j<=n;++j){//下边界
            int last=0;
            for (rint k=1;k<=n;++k)//第一个1
                if (sum[j][k]-sum[i-1][k])  res=(res+(k-last)*(n-k+1))%mod,last=k;
        }
    return res;
}
//}}}
int main()
{
    cin>>n;
    for (rint i=1;i<=n;++i)
        for (rint j=1;j<=n;++j)
            cin>>a[i][j],mx=max(mx,a[i][j]);
    all=n*(n+1)/2%mod;
    all=1ll*all*all%mod;
    for (rint k=0;k<=31;++k){
        int t=1<<k;
        if (t>mx)   break;
        int num=calc(t,1);
        num=(all-num+mod)%mod;
        ans1=(ans1+1ll*num*t%mod)%mod;
        num=calc(1<<k,0);
        ans2=(ans2+1ll*num*t%mod)%mod;
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}

\ (100 \) points

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年09月10日 星期二 14时17分44秒
*******************************/
#include <cstdio>
#include <fstream>
#include <algorithm>
using namespace std;
const int maxn = 1003;
const int mod = 1000000007;
//{{{cin
struct IO{
    template<typename T>
    IO & operator>>(T&res){
        res=0;
        bool flag=false;
        char ch;
        while((ch=getchar())>'9'||ch<'0')   flag|=ch=='-';
        while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
        if (flag)   res=~res+1;
        return *this;
    }
}cin;
//}}}
int n,mx,all,ans1,ans2;
int stk[maxn];
int a[maxn][maxn],f[maxn][maxn];
bool b[maxn][maxn];
//{{{calc
inline int calc (int mi,bool opt)
{
    int res=0;
    for (int i=1;i<=n;++i)
        for (int j=1;j<=n;++j){
            b[i][j]=(a[i][j]&mi);
            b[i][j]^=opt;
            f[i][j]=b[i][j]?f[i-1][j]+1:0;
        }
    for (int i=1;i<=n;++i){
        int cnt=0,top=0;
        for (int j=1;j<=n;++j){
            cnt+=f[i][j];
            while (top&&f[i][stk[top]]>f[i][j]) cnt-=(stk[top]-stk[top-1])*(f[i][stk[top]]-f[i][j]),--top;
            res=(res+cnt)%mod;
            stk[++top]=j;
        }
    }
    return res;
}
//}}}
int main()
{
    cin>>n;
    for (int i=1;i<=n;++i)
        for (int j=1;j<=n;++j)
            cin>>a[i][j],mx=max(mx,a[i][j]);
    all=n*(n+1)/2%mod;
    all=1ll*all*all%mod;
    for (int k=0;k<=31;++k){
        int t=1<<k;
        if (t>mx)   break;
        int num=calc(t,0);
        ans1=(ans1+1ll*num*t%mod)%mod;
        num=calc(1<<k,1);
        num=(all-num+mod)%mod;
        ans2=(ans2+1ll*num*t%mod)%mod;
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}

If not quite understand where to put it or there is an error, please correct me
if you like, you may wish to point a collection of praise about it

Guess you like

Origin www.cnblogs.com/Morning-Glory/p/11506347.html