• LG5300 「GZOI2019/GXOI2019」与或和 二进制+单调栈


    问题描述

    Freda 学习了位运算和矩阵以后,决定对这种简洁而优美的运算,以及蕴含深邃空间的结构进行更加深入的研究。

    对于一个由非负整数构成的矩阵,她定义矩阵的 ( exttt{AND}) 值为矩阵中所有数二进制 ( exttt{AND(&)}) 的运算结果;定义矩阵的 ( exttt{OR}) 值为矩阵中所有数二进制 ( exttt{OR(|)}) 的运算结果。

    给定一个 (N imes N) 的矩阵,她希望求出:

    1. 该矩阵的所有子矩阵的 ( exttt{AND}) 值之和(所有子矩阵 ( exttt{AND}) 值相加的结果)。
    2. 该矩阵的所有子矩阵的 ( exttt{OR}) 值之和(所有子矩阵 ( exttt{OR}) 值相加的结果)。

    接下来的剧情你应该已经猜到——Freda 并不想花费时间解决如此简单的问题,所以这个问题就交给你了。

    由于答案可能非常的大,你只需要输出答案对 (1,000,000,007 (10^9 + 7)) 取模后的结果。

    LG5300


    题解

    发现 and 和 or 大毒瘤出现开幕雷击,于是考虑按位计算贡献。

    问题就简化为了01矩阵。

    于是一个子矩阵全是0的话对or有负贡献,全是1的话对and有正贡献。

    单调栈维护即可


    (mathrm{Code})

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    template <typename Tp>
    void read(Tp &x){
    	x=0;char ch=1;int fh=1;
    	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    	if(ch=='-') ch=getchar(),fh=-1;
    	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    	x*=fh;
    }
    
    const int mod=1000000007;
    const int maxn=1007;
    
    int a[maxn][maxn],n;
    long long ansor,ansand;
    int s[maxn],h[maxn],val[maxn],pos;
    int mx;
    
    void Init(void){
    	read(n);
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
    		read(a[i][j]),mx=max(mx,a[i][j]);
    }
    
    long long sqr(long long x){
    	return (long long)x*(x+1)/2;
    }
    
    int calc(int need){
    	long long res=0;
    	memset(h,0,sizeof(h));
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if((a[i][j]&1)==need) h[j]++;
    			else h[j]=0;
    			if(h[j]>s[pos]) s[++pos]=h[j],val[pos]=1;
    			else{
    				int k=0;
    				while(h[j]<s[pos]){
    					k+=val[pos];
    					res=(res+(s[pos]-max(s[pos-1],h[j]))*sqr(k)%mod)%mod;
    					--pos;
    				}
    				s[++pos]=h[j],val[pos]=k+1;
    			}
    		}
    		int k=0;
    		while(pos){
    			k+=val[pos];
    			res=(res+(s[pos]-s[pos-1])*sqr(k)%mod)%mod;
    			--pos;
    		}
    	}
    	return res;
    }
    
    void Work(void){
    	int tp=0;
    	while(mx){
    		ansand=(ansand+calc(1)*(1<<tp)%mod)%mod;
    		ansor=(ansor+(sqr(n)*sqr(n)%mod-calc(0))*(1<<tp)%mod)%mod;
    		mx>>=1;tp++;
    		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]>>=1;
    	}
    	ansand=(ansand%mod+mod)%mod;
    	ansor=(ansor%mod+mod)%mod;
    	printf("%lld %lld
    ",ansand,ansor);
    }
    
    signed main(){
    //	freopen("andorsum.in","r",stdin);freopen("andorsum.out","w",stdout);
    	Init();
    	Work();
    }
    
  • 相关阅读:
    Oracle导出导入表空间创建
    ASP.NET 缓存 SqlCacheDependency 监视数据库表变化 让缓存更新的更及时更提高节能
    Silverlight在添加WCF服务引用时报错
    springboot中如何动态更换 配置文件 spring.profiles.active
    maven之根据profile动态切换resource
    java synchronized 关键字的锁升级过程
    子类中的方法和父类同名,但是参数不同,是重写(overload)不是覆盖(override)
    Java的协变(extends)和逆变(super),说白了都是子类的实例赋值给父类的变量
    Mybatis缓存
    [转]Spring MVC之 @PathVariable @CookieValue@RequestParam @RequestBody @RequestHeader@SessionAttributes, @ModelAttribute
  • 原文地址:https://www.cnblogs.com/liubainian/p/12181424.html
Copyright © 2020-2023  润新知