[LOJ3083] [GXOI2019] 與或和
阿新 • • 發佈:2019-05-12
sta sdi ack clas %d tmp cpp 個數 putchar
題目鏈接
LOJ:https://loj.ac/problem/3083
洛谷:https://www.luogu.org/problemnew/show/P5300
Solution
逐位考慮,可以發現問題就是求一個\(\rm 01\)矩陣的全\(\rm 0\)子矩形個數。
那麽我們可以用一個上升的單調棧來求這個,總復雜度\(O(n^2\log v)\)。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define ll long long #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 1e3+10; const int inf = 1e9; const lf eps = 1e-8; const int mod = 1e9+7; int add(int x,int y) {return x+y>=mod?x+y-mod:x+y;} int del(int x,int y) {return x-y<0?x-y+mod:x-y;} int mul(int x,int y) {return 1ll*x*y-1ll*x*y/mod*mod;} int s[maxn][maxn],a[maxn][maxn],in[maxn][maxn],n,ans1,ans2,top,sta[maxn]; int calc() { FOR(i,1,n) FOR(j,1,n) s[i][j]=a[i][j]*(s[i-1][j]+1); ll res=0; FOR(i,1,n) { sta[top=0]=0;ll tmp=0; FOR(j,1,n) { tmp+=s[i][j]; while(top&&s[i][sta[top]]>=s[i][j]) tmp-=(s[i][sta[top]]-s[i][j])*(sta[top]-sta[top-1]),top--; //彈棧的時候把不合法貢獻減去 sta[++top]=j;res+=tmp; } }return res%mod; } void solve(int x) { FOR(i,1,n) FOR(j,1,n) a[i][j]=(in[i][j]>>x)&1; ans1=add(ans1,mul(calc(),1<<x)); FOR(i,1,n) FOR(j,1,n) a[i][j]^=1,ans2=add(ans2,mul(i*j,1<<x)); ans2=del(ans2,mul(calc(),1<<x)); } int main() { read(n);FOR(i,1,n) FOR(j,1,n) read(in[i][j]); FOR(i,0,30) solve(i);printf("%d %d\n",ans1,ans2); return 0; }
[LOJ3083] [GXOI2019] 與或和