zoukankan      html  css  js  c++  java
  • test20190903 JKlover

    100+65+100=265,T2就差了一点。

    乌合之众

    给出一个 n × n 的, 元素为自然数的矩阵.这个矩阵有许许多多个子矩阵, 定义它的所有子矩阵形成的集合为 S .

    对于一个矩阵 k , 定义 f(k) 为 k 中所有元素的 AND 值 (按位与).

    对于一个矩阵 k , 定义 g(k) 为 k 中所有元素的 OR 值 (按位或).

    请求出所有子矩阵的 f(k) 之和与所有子矩阵的 g(k) 之和, 即 ∑k∈Sf(k) 与 ∑k∈Sg(k) .

    由于答案可能很大, 只需要输出答案对 998244353 取模的结果.

    对于 100% 的数据, n ≤ 103, 矩阵中的每个元素都在 int 范围内. 数据有一定梯度.

    题解

    各个二进制位无关,可以每位分开做。

    发现 AND 求的就是全1子矩阵的个数,OR 类似。

    那么用单调栈解决即可。时间复杂度 O(n2)。

    #include<bits/stdc++.h>
    using namespace std;
    template<class T> T read(){
    	T x=0,w=1;char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*w;
    }
    template<class T> T read(T&x){
    	return x=read<T>();
    }
    #define co const
    #define il inline
    typedef long long LL;
    
    co int mod=998244353,i2=499122177;
    il int add(int a,int b){
    	return (a+=b)>=mod?a-mod:a;
    }
    il int mul(int a,int b){
    	return (LL)a*b%mod;
    }
    
    co int N=1000+10;
    int n,a[N][N];
    int h[N],s[N],st[N],top;
    
    int main(){
    	freopen("mob.in","r",stdin),freopen("mob.out","w",stdout);
    	read(n);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;++j) read(a[i][j]);
    	int ans=0;
    	for(int c=0;c<31;++c){
    		fill(h+1,h+n+1,0);
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j) h[j]=a[i][j]>>c&1?h[j]+1:0;
    			int sum=0;
    			top=0;
    			for(int j=1;j<=n+1;++j){
    				while(top&&h[st[top]]>=h[j])
    					sum=add(sum,mod-s[top]),--top;
    				st[++top]=j,s[top]=mul(h[j],j-st[top-1]);
    				sum=add(sum,s[top]),ans=add(ans,mul(sum,1<<c));
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	ans=0;
    	int bas=mul(n*(n+1)/2,n*(n+1)/2);
    	for(int c=0;c<31;++c){
    		ans=add(ans,mul(bas,1<<c));
    		fill(h+1,h+n+1,0);
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j) h[j]=~a[i][j]>>c&1?h[j]+1:0;
    			int sum=0;
    			top=0;
    			for(int j=1;j<=n+1;++j){
    				while(top&&h[st[top]]>=h[j])
    					sum=add(sum,mod-s[top]),--top;
    				st[++top]=j,s[top]=mul(h[j],j-st[top-1]);
    				sum=add(sum,s[top]),ans=add(ans,mod-mul(sum,1<<c));
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    圣战

    有 n 个人想要加入圣战, 每个人需要选择一个阵营加入.

    但他们私下有 m 对敌对关系, 有敌对关系的两个人不会加入同一个阵营.

    很快, 他们发现这会让他们难以加入到圣战中, 于是有一对敌人和好了, 即去除了一对敌对关系.

    请找出去除哪一对关系后, 能找到一种加入阵营的方案, 使得剩余有敌对关系的人都不在同一个阵营.

    为了避免输出文件过大, 你只需要输出所有符合题意的关系编号的异或和.

    对于 100% 的数据, n, m ≤ 5 × 105

    数据保证不会给出重复的敌对关系, 也保证自己不会与自己是敌对关系.

    题解

    二分图就是图中不存在奇环的图, 所以一张二分图删掉若干条边之后, 一定还是一张二分图.

    先假设原图连通, 于是可以做出原图的一棵生成树.

    然后再加入剩余的非树边. 若加入了非树边 (u, v) , 那么树上 u → v 的路径上的边都被这条非树边覆盖了.

    记 dis(u, v) 表示 u, v 在树上的距离.
    若 dis(u, v) 为奇数, 则加入 (u, v) 后会形成偶环, 称这条边合法.
    若 dis(u, v) 为偶数, 则加入 (u, v) 后会形成奇环, 称这条边不合法.

    记不合法边的总数为 cnt , 然后分类讨论.

    1. cnt = 0 , 答案为所有边.
    2. cnt = 1 , 答案为唯一的那条不合法边, 以及树上被它覆盖, 但未被合法边覆盖
      的边.
    3. cnt > 1 , 答案为树上被所有不合法边覆盖, 但未被合法边覆盖的边.

    考虑正确性的证明, 若一条树边被所有不合法边覆盖, 也被若干条合法边覆盖.

    那么断掉它之后, 原来的奇环走到对应位置时可以走一个偶环回来, 仍存在奇环.所以还要求不被合法边覆盖.

    判断覆盖次数可以树上差分, 被不合法边覆盖权值 +1 , 被合法边覆盖权值 −1 .

    若最后的权值 = cnt , 则这条边就可以计入答案.

    原图可以不连通, 所以对每个联通块分别执行以上算法, 注意 cnt 是所有联通块的 cnt 之和.

    时间复杂度 O(n) , 期望得分 100 分.

    #include<bits/stdc++.h>
    using namespace std;
    template<class T> T read(){
    	T x=0,w=1;char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*w;
    }
    template<class T> T read(T&x){
    	return x=read<T>();
    }
    #define co const
    #define il inline
    typedef long long LL;
    
    co int N=500000+10;
    struct edge {int to,id,next;}e[N*2];
    int head[N],ecnt=1;
    
    void add_edge(int u,int v,int id){
    	e[++ecnt]=(edge){v,id,head[u]},head[u]=ecnt;
    	e[++ecnt]=(edge){u,id,head[v]},head[v]=ecnt;
    }
    
    int dfn[N],tag[N],cnt,tmp;
    
    void dfs(int x,int in_edge){
    	for(int i=head[x];i;i=e[i].next){
    		if(i==(in_edge^1)) continue;
    		int y=e[i].to;
    		if(!dfn[y]){
    			dfn[y]=dfn[x]+1,dfs(y,i);
    			tag[x]+=tag[y];
    		}
    		else if(dfn[y]<dfn[x]){
    			if((dfn[x]-dfn[y]+1)&1){ // invalid edge
    				++tag[x],--tag[y];
    				++cnt,tmp=e[i].id;
    			}
    			else --tag[x],++tag[y]; // valid edge
    		}
    	}
    }
    
    int vis[N],ans[N],tot;
    
    void calc(int x){
    	vis[x]=1;
    	for(int i=head[x];i;i=e[i].next){
    		int y=e[i].to;
    		if(vis[y]) continue;
    		if(tag[y]==cnt) ans[++tot]=e[i].id;
    		calc(y);
    	}
    }
    
    int main(){
    	freopen("crusade.in","r",stdin),freopen("crusade.out","w",stdout);
    	int n=read<int>(),m=read<int>();
    	for(int i=1;i<=m;++i) add_edge(read<int>(),read<int>(),i);
    	for(int i=1;i<=n;++i)
    		if(!dfn[i]) dfn[i]=1,dfs(i,0);
    	if(!cnt){
    		printf("%d
    ",m);
    		int sum=0;
    		for(int i=1;i<=m;++i) sum^=i;
    		printf("%d
    ",sum);
    		return 0;
    	}
    	for(int i=1;i<=n;++i)
    		if(!vis[i]) calc(i);
    	if(cnt==1) ans[++tot]=tmp;
    	printf("%d
    ",tot);
    	int sum=0;
    	for(int i=1;i<=tot;++i) sum^=ans[i];
    	printf("%d
    ",sum);
    	return 0;
    }
    

    这题刘老爷数据出锅,详见博客

    花火之声不闻于耳

    有一个长度为 n 的正整数序列 a , 你需要进行 m 次操作, 每次操作有如下两种类型:

    修改: (L, R, x) , 表示将区间 [L, R] 内的 ai 都乘上一个正整数 x .

    询问: (L, R) , 询问区间 [L, R] 内每个数的乘积的欧拉函数值, 即 φ(∏i=L~Rai)

    由于答案可能很大, 你只需要输出答案对 998244353 取模的结果.

    这里的欧拉函数 φ(x) 定义为小于等于 x 的正整数中, 与 x 互质的数的个数.

    对于 100% 的数据, op ∈ {1, 2}, n, m ≤ 4 × 105, x ≤ 300 , 初始的 ai ≤ 300 .

    题解

    将欧拉函数定义式写出来,我们就知道我们要维护乘积和质因子。

    300以内质数个数有62个,用long long压位即可。

    注意预处理卡常,因为每次都求逆元是两个 log 的。

    时间复杂度 O(n log n)。

  • 相关阅读:
    log4j配置只打印指定jar或包的DEBUG信息
    实现cookie跨域访问
    使用轻量级Spring @Scheduled注解执行定时任务
    Docker容器里时间与宿主机不同步
    Wildfly8 更改response header中的Server参数
    JBoss部署项目log4j配置会造成死锁问题,浏览器访问一直pending状态
    json-lib-2.4.jar Bug,json字符串中value为"[value]"结构时,解析为数组,不会解析成字符串
    【转载】分享下多年积累的对JAVA程序员成长之路的总结
    web项目嵌入Jetty运行的两种方式(Jetty插件和自制Jetty服务器)
    rabbitmq+haproxy+keepalived实现高可用集群搭建
  • 原文地址:https://www.cnblogs.com/autoint/p/test20190903.html
Copyright © 2011-2022 走看看