• 模拟赛41 题解


    T1

    考场上一看到暴力有70分就没有去想正解。当时脑子里闪过了先处理两个相加,再询问。但是当时感觉可能会算重复,就没有继续往下想。
    但是应该是没有重复的。因为顺序不同也算不同方案。。
    因为100000内的质数只有9000多个,所以可以定义dp[i]为i能被两个质数相加得到的方案数。然后(n^2)求出。
    对于每个n,只需O(n)求出答案即可。

    代码:
    
    
    #include <bits/stdc++.h>
    using namespace std;  
    typedef long long ll;
    const int maxn=100000+10;
    int read(){
    	int w=0,x=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') x=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		w=(w<<1)+(w<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*w;
    }
    int n,cnt;
    int prime[maxn];
    bool is_not_prime[maxn];
    ll dp[maxn<<1];
    ll ans;
    void xxs(){
    	is_not_prime[0]=is_not_prime[1]=1;
    	for(register int i=2;i<=100000;++i){
    		if(!is_not_prime[i]) prime[++cnt]=i;
    		for(register int j=1;j<=cnt&&i*prime[j]<=100000;++j){
    			is_not_prime[prime[j]*i]=1;
    			if(i%prime[j]==0) break;
    		}
    	}
    	for(register int i=1;i<=cnt;++i){
    		for(register int j=1;j<=cnt;++j){
    			if(prime[i]+prime[j]<=100000) dp[prime[i]+prime[j]]++;
    		}
    	}
    }
    void Solve(){
    	xxs();
    	int T=read();
    	while(T--){
    		n=read();
    		ll ans=0;
    		for(register int i=1;i<=n;++i) ans+=dp[i]*dp[n-i];
    		printf("%lld
    ",ans);
    	}
    }
    int main(){
    	freopen("plus.in","r",stdin);
    	freopen("plus.out","w",stdout);
    	Solve();
    	return 0;
    }
    
    

    T2

    转化为01trie。发现对于[l,r],假如两个区间[l,mid],[mid+1,r]完全相同,那么就是这一位取0或1都行于是返回F(l,mid)2。
    如果两个区间没有交,那么就是分开讨论,再相乘,即F(l,mid+1)
    F(mid+1,r);
    如果两种情况都没出现,那么一定无解。
    边界F(x,x)=1;
    (其实可以先在OJ上交一发printf('0');,然后发现0分,证明没有无解的情况,于是每次比较两个区间的时候只需要比较第一个元素即可,然后就跑成了最优解233)

    代码:
    
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1<<17,mod=1e9+7;
    #define gc() (p1 == p2 ? (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2 ? EOF : *p1++) : *p1++)
    #define read() ({ register int x = 0, f = 1; register char c = gc(); while(c < '0' || c > '9') { if (c == '-') f = -1; c = gc();} while(c >= '0' && c <= '9') x = x * 10 + (c & 15), c = gc(); f * x; })
    char buf[1 << 20], *p1, *p2;
    int m,n;
    int p[maxn];
    int ans;
    int Devide(int l,int r){
    	if(l==r) return 1;
    	int mid=(l+r)>>1;
    	bool flag=0;
    	if(p[l]==p[mid+1]) return 2*Devide(l,mid)%mod;
    	return 1ll*Devide(l,mid)*Devide(mid+1,r)%mod;
    }
    void Solve(){
    	m=read();
    	n=read();
    	for(int i=1;i<=(1<<m);++i) p[i]=read();
    	ans=Devide(1,1<<m);
    	printf("%d
    ",ans);
    }
    int main(){
    	freopen("match.in","r",stdin);
    	freopen("match.out","w",stdout);
    	Solve();
    	return 0;
    }
    
    
    

    T3

    这题转化完了之后竟然是原题。。操
    发现一条边是黑边的条件,就是两个端点被不同的修改操作修改过。
    因此可以打时间戳,最后询问路径有多少连续相等的段。
    于是就是luogu P2486 [SDOI2011]染色了,具体怎么维护链接里有。

    代码:
    
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=500000+10,Inf=0x3f3f3f3f;
    struct node{
    	int to,next;
    }edge[maxn<<1];
    int head[maxn],top[maxn],size[maxn],son[maxn],fa[maxn],depth[maxn],dfn[maxn];
    int n,m,cnt,Time,tim;
    struct Segment_tree{
    	int val,lazy,lc,rc;//lc,rc分别表示这个区间左右端点的color,lazy==-1时表示没有赋值
    }tree[maxn<<2];
    int read(){
    	int w=0,x=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') x=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		w=(w<<1)+(w<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*w;
    }
    void add(int from,int to){
    	edge[++cnt].to=to;
    	edge[cnt].next=head[from];
    	head[from]=cnt;
    }
    void dfs1(int u,int f){
    	size[u]=1;
    	fa[u]=f;
    	for(int i=head[u];i;i=edge[i].next){
    		int v=edge[i].to;
    		if(v==f) continue;
    		depth[v]=depth[u]+1;
    		dfs1(v,u);
    		size[u]+=size[v];
    		if(size[v]>size[son[u]]) son[u]=v;
    	}
    }
    void dfs2(int u,int t){
    	top[u]=t;
    	dfn[u]=++Time;
    	if(son[u]) dfs2(son[u],t);
    	for(int i=head[u];i;i=edge[i].next){
    		int v=edge[i].to;
    		if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
    	}
    }
    void pushup(int rt){
    	tree[rt].lc=tree[rt<<1].lc;
    	tree[rt].rc=tree[rt<<1|1].rc;
    	tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val-(tree[rt<<1].rc==tree[rt<<1|1].lc);
    }
    void update(int rt,int x){
    	tree[rt].lazy=x;
    	tree[rt].val=1;
    	tree[rt].lc=tree[rt].rc=x;
    }
    void pushdown(int rt){
    	if(tree[rt].lazy==-1) return;
    	tree[rt].val=1;
    	update(rt<<1,tree[rt].lazy);
    	update(rt<<1|1,tree[rt].lazy);
    	tree[rt].lazy=-1;
    }
    void modify(int rt,int l,int r,int s,int t,int p){
    	if(s<=l&&r<=t){
    		update(rt,p);
    		return;
    	}
    	int mid=(l+r)>>1;
    	pushdown(rt);
    	if(s<=mid) modify(rt<<1,l,mid,s,t,p);
    	if(t>mid) modify(rt<<1|1,mid+1,r,s,t,p);
    	pushup(rt);
    }
    void build(int rt,int l,int r){
    	tree[rt].lazy=-1;
    	if(l==r){
    		tree[rt].val=1;
    		tree[rt].lc=tree[rt].rc=l;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(rt<<1,l,mid);
    	build(rt<<1|1,mid+1,r);
    	pushup(rt);
    }
    int query2(int rt,int l,int r,int x){
    	if(l==r) return tree[rt].lc;
    	int mid=(l+r)>>1;
    	pushdown(rt);
    	if(x<=mid) return query2(rt<<1,l,mid,x);
    	else return query2(rt<<1|1,mid+1,r,x);
    }
    int query(int rt,int l,int r,int s,int t){
    	if(s<=l&&r<=t) return tree[rt].val;
    	int mid=(l+r)>>1;
    	pushdown(rt);
    	if(t<=mid) return query(rt<<1,l,mid,s,t);
    	if(s>mid) return query(rt<<1|1,mid+1,r,s,t);
    	return query(rt<<1,l,mid,s,t)+query(rt<<1|1,mid+1,r,s,t)-(tree[rt<<1].rc==tree[rt<<1|1].lc);
    }
    int Query(int u,int v){
    	if(u==v) return 1;
    	int res=0;
    	while(top[u]!=top[v]){
    		if(depth[top[u]]<depth[top[v]]) swap(u,v);
    		//printf("u==%d v==%d
    ",u,v);
    		res+=query(1,1,n,dfn[top[u]],dfn[u]);
    		//printf("dfn[top[u]]=%d dfn[u]=%d
    ",dfn[top[u]],dfn[u]);
    		if(top[u]!=1){
    			int sss=query2(1,1,n,dfn[top[u]]);
    			int ssss=query2(1,1,n,dfn[fa[top[u]]]);
    			//printf("sss=%d ssss=%d
    ",sss,ssss);
    			if(sss==ssss) res--;	
    			//if(top[u]!=1 && query2(1,1,n,dfn[top[u]])==query2(1,1,n,dfn[fa[top[u]]])) res--;
    		}
    		u=fa[top[u]];
    	}
    	if(depth[u]>depth[v]) swap(u,v);
    	res+=query(1,1,n,dfn[u],dfn[v]);
    	return res;
    }
    void Modify(int u,int v,int x){
    	while(top[u]!=top[v]){
    		if(depth[top[u]]<depth[top[v]]) swap(u,v);
    		modify(1,1,n,dfn[top[u]],dfn[u],x);
    		u=fa[top[u]];
    	}
    	if(depth[u]>depth[v]) swap(u,v);
    	modify(1,1,n,dfn[u],dfn[v],x);	
    }
    void Solve(){
    	n=read();
    	for(int i=1,x,y;i<n;++i){
    		x=read();
    		y=read();
    		add(x,y);
    		add(y,x);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	build(1,1,n);
    	//for(int i=1;i<=n;++i) printf("fa[%d]=%d son[%d]=%d depth[%d]=%d top[%d]=%d size[%d]=%d dfn[%d]=%d
    ",i,fa[i],i,son[i],i,depth[i],i,top[i],i,size[i],i,dfn[i]);
    	m=read();
    	tim=n;
    	for(int i=1,op,x,y,z;i<=m;++i){
    		op=read();
    		x=read();
    		y=read();
    		if(op==0){
    			int res=Query(x,y);
    			printf("%d
    ",res-1);
    		}
    		else{
    			tim++;
    			Modify(x,y,tim);
    		}
    	}
    }
    int main(){
    	freopen("colour.in","r",stdin);
    	freopen("colour.out","w",stdout);
    	Solve();
    	return 0;
    }
    
    

    T4

    不会

  • 相关阅读:
    UCSC genome browser 个人track 安装
    C++遍历二维数组的四种方法
    生物结构变异分析软件meerkat 0.189使用笔记(一)
    R语言从小木虫网页批量提取考研调剂信息
    使用R语言将微信记录制作成词云(简洁)--情人节奥义
    判断数据是否服从某一分布(二)——简单易用fitdistrplus包
    判断数据是否服从某一分布(一)
    如何正确地写出单例模式
    使用 JavaScript 将网站后台的数据变化实时更新到前端-【知乎总结】
    C#实时读取数据----局部页面刷新【转】
  • 原文地址:https://www.cnblogs.com/wwcdcpyscc/p/14049568.html
Copyright © 2020-2023  润新知