[GXOI / GZOI2019]及び又は[単調スタック]

おそらく、より良い読書体験

\(\ mathcal {説明} \)

得られる(N回\ n \)\を、要素がマトリックスの自然数である。
このマトリックスを形成そのサブマトリックスの全ての集合された定義、多くのサブマトリックスを有する(S \)を\を
マトリックスについて\(K \)の定義\(F(K)\)\(K \)のすべての要素で\(および\)の値(ビット単位のAND)。
マトリックスのための\(K \) 定義された\(G(k)は\)\(K \)のすべての要素で\(または\)の値(ビット単位のOR)。
すべてのサブ行列の要求\(F(k)を\)すべてのサブ行列の和\(G(kは)\)の和、すなわち、\(\開始{整列} \ F(k)はsum_ {SのK \} \端{整列} \) と\(\開始{整列} \ sum_ {SのK \} G (K)\端{整列}
\) 答えは、答えのみ出力する必要があるために大きくなければ(1E9 + 7 \)\モジュロ結果。

\(N \、leq1000を\)行列の各要素の大きさ(INT \)\の範囲内

\(\ mathcal {解決} \)

算術演算のための一つのトピックは、最初の検討の寄与を計算する方法は、ビットの寄与にある
寄与が他のビットのビットは影響を受けませんされているのでため、特殊ビット・コンピューティングの全体的なコンピューティングは、またはによって考慮されるが、ビット・コンピューティング

我々は、すべての列挙\(Kを\)に、次いでマトリックス、\(0/1 \)マトリックス、\(0 \)要素は、元の行列要素はバイナリに列挙を表しされている(0 \)\として、\(1 \)と比較して、\(1 \)を
考える\(0/1 \)サブ行列寄与の数の行列が計算され、最終的に乗じ、この数置く\を(2 ^ K \)

どのように多くのフル依頼することです操作については、\(1 \)行列
しているどのように多くの尋ねることであるためか、操作、(1 \)\行列は、

そして演算は、実際に可能な交換又は
完全\(1 \)マトリックスマトリックス=すべての数-で\(0 \)行列
\(1 \)マトリックスマトリックス=すべての数-フル\(0 \)行列番号

セット\(すべて\)\(N \回N \)すべての部分行列が行列に含まれる
明確される\({すべて=(\ FRAC )N(N + 1} {2})^ 2 \)

条件を満たす行列の数を計算する方法を検討した後

\(55 \)分解\(O(log_2n \ CDOTのn
^ 3)\) 注意事項列挙境界マトリックス、下限
私たちは、このようなマトリックスでの出会いを求めている要件の数を数える
、\(1 \)行列明確に行うのは簡単
左端の行列に列挙を考慮すると、\(1 \)が場所を表示され
ますが、すべてのコンピューティングをリークしていないことができるように
限り、これが含まれているように、明らかに\(1 \)を一つで、すべての行列は、現在のスコープ内にあります法的
に注意していない\(1 \)の列を繰り返し、

\([I]和[jを ] \) を表し\(J \)カラムを(私は\)\総数位置\(1 \)
長い\(SUM [下縁] [現在の列] -sumを【境界-1] [現在の列]> 0 \)これが記載されている説明する\(1 \)
コードを見ながら、特にその上に他の非常に単純な、

\(100 \)分解\(O(log_2n \ CDOT N ^ 2)\)

列挙がマトリックスの下側の境界を考慮
完全に計算される(1 \)\をマトリックス
([I] [Jは、F \ ] \) を表し\(J \)からカラム\を(私は\)がアップ始めたどのように多くの連続\(1 \)
とここで列挙し、で\(CNTの\)番号は、各行列表現を増加させる
ことを維持するために、単調なスタックと

\(\ mathcal {コード} \)

\(55 \)分の
運カードしばしば版を試します

/*******************************
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 \)ポイント

/*******************************
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;
}

かなりそれをどこに置くか理解したり、エラーがあるない場合は、私を修正してください
あなたが好きならば、あなたはそれについて賞賛のコレクションを指すように望むこと

おすすめ

転載: www.cnblogs.com/Morning-Glory/p/11506347.html