zoukankan      html  css  js  c++  java
  • HZOI20190818模拟25题解

    题面:https://www.cnblogs.com/Juve/articles/11372379.html

    A:字符串

    其实是CATALAN数水题。。。

    和网格一毛一样:https://www.cnblogs.com/Juve/p/11222358.html

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 20100403
    #define int long long
    using namespace std;
    int n,m,ans=0;
    int q_pow(int a,int b,int p){
    	int res=1;
    	while(b){
    		if(b&1) res=(res*a)%p;
    		a=(a*a)%p;
    		b>>=1;
    	}
    	return res%p;
    }
    int fac(int n){
    	if(n==1||n==0) return 1;
    	int res=1;
    	for(int i=2;i<=n;i++)
    		res=(res*i)%mod;
    	return res%mod;
    }
    int inv(int n){
    	if(n==0) return 1;
    	return q_pow(fac(n),mod-2,mod)%mod;
    }
    int C(int n,int m){
    	if(n==m) return 1;
    	if(n<m) return 0;
    	return fac(n)*inv(m)%mod*inv(n-m)%mod;
    }
    signed main(){
    	scanf("%lld%lld",&n,&m);
    	ans=C(n+m,n)*q_pow(m+1,mod-2,mod)%mod*(n-m+1)%mod;
    	printf("%lld
    ",ans%mod);
    	return 0;
    }
    

    B:乌鸦坐飞机喝水

    乌鸦喝水是“能喝的时候一定喝”的,所以和DP决策没关系。

    直接模拟的复杂度为O(nm)

    把每个水缸按照可以喝水的次数(即喝多少次水,水位下降到喝不到)由小到大排序,依次处理。

    显然如果前面的水缸能喝n次,后面的水缸至少也能喝n次,这个性质十分有用。

    由上面这句话可以推出:如果乌鸦从当前位置飞到队伍末会经过k个能喝的水缸,而当前水缸还能喝的次数x>=k,那么之后的水缸也不会在这一轮被喝空。

    1、枚举每一个水缸开始(在枚举到该水缸的时候,前面剩余次数更小的水缸已经被喝完。或者可以理解为,舍弃前面的缸,贪心喝这个。)

    2、用树状数组维护水缸的ID,查询从当前水缸的ID到(原先的)第n个水缸还有多少个能喝的水缸,如果当前缸的剩余次数>=剩余缸数,直接更新次数并跳到下一轮。

    3、在数次2操作后,当前缸的剩余次数<=剩余缸数,此时在树状数组上二分“余数”,即喝到又一轮的某位置时,当前缸没水了。

    4、将当前缸标为空,枚举下一个水缸。

    表面看着复杂度高,实际上喝水的次数不会超过最多的那个缸能喝的次数(因为每次喝水都是所有缸水位一起下降的),同时,模拟操作的次数不会超过m(最多喝m轮),复杂度可以接受。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define int long long
    #define MAXN 100005
    using namespace std;
    int n,m,x;
    struct node{
    	int d,a,id,tim;
    	friend bool operator < (node a,node b){
    		return a.tim<b.tim;
    	}
    }w[MAXN];
    struct BITREE{
    	int c[MAXN];
    	int lowbit(int x){
    		return x&(-x);
    	}
    	void update(int pos,int val){
    		for(int i=pos;i<=n;i+=lowbit(i))
    			c[i]+=val;
    	}
    	int query(int pos){
    		int res=0;
    		for(int i=pos;i;i-=lowbit(i))
    			res+=c[i];
    		return res;
    	}
    }BIT;
    int last=0,now=0,ans=0;
    int find(int x){
    	int res=last,l=last,r=n;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(BIT.query(mid)-BIT.query(last)<=x)
    			res=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return res;
    }
    signed main(){
    	scanf("%lld%lld%lld",&n,&m,&x);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&w[i].d);
    		w[i].id=i;
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&w[i].a);
    		w[i].tim=(x-w[i].d)/w[i].a+1;
    		BIT.update(w[i].id,1);
    	}
    	sort(w+1,w+n+1);
    	for(int i=1;i<=n;i++){
    		if(w[i].tim<ans){
    			BIT.update(w[i].id,-1);
    			continue;
    		}
    		while(now<m){
    			int sum=BIT.query(n)-BIT.query(last);
    			if(sum+ans>w[i].tim) break;
    			ans+=sum;
    			last=0;
    			now++;
    		}
    		if(now>=m) break;
    		last=find(w[i].tim-ans);
    		ans=w[i].tim;
    		BIT.update(w[i].id,-1);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    C:所驼门王的宝藏

    %%AlpaCa羊驼哥

    题面挺吓人,但是水题一个

    首先你要从提干中的输入建出图来

    建图非常sb

    我定义了两个vector,存每行每列的宫殿坐标及类型

    然后扫描每行,搜到一个横天门就把它和这一行每一个宫殿连边,其他同理,

    然后就和之前的爆炸行动一样了,

    tarjan缩点,然后在新建的图上跑拓扑,找到新图上的最长链

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define MAXK 1000005
    #define re register
    using namespace std;
    int n,m,k,ans=0,res[MAXK];
    struct node{
    	int opt,id,x,y;
    };
    vector<node>h[MAXK],l[MAXK];
    struct EDGE{
    	int to,nxt;
    }e[MAXK<<2];
    int head[MAXK],cnt=0;
    inline void add(re int u,re int v){
    	cnt++,e[cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;
    }
    int dfn[MAXK],low[MAXK],sta[MAXK],top=0,dfs_order=0,tot=0,belong[MAXK],siz[MAXK];
    bool in_sta[MAXK];
    inline void tarjan(re int x){
    	dfn[x]=low[x]=++dfs_order;
    	sta[++top]=x;
    	in_sta[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt){
    		re int y=e[i].to;
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(in_sta[y]) low[x]=min(low[x],dfn[y]);
    	}
    	if(dfn[x]==low[x]){
    		tot++;
    		re int y;
    		do{
    			y=sta[top--];
    			in_sta[y]=0;
    			belong[y]=tot;
    			siz[tot]++;
    		}while(y!=x);
    	}
    }
    int to[MAXK<<2],nxt[MAXK<<2],pre[MAXK],sum=0;
    inline void ADD(re int u,re int v){
    	sum++,to[sum]=v,nxt[sum]=pre[u],pre[u]=sum;
    }
    int in_deg[MAXK];
    queue<int>q;
    int main(){
    	scanf("%d%d%d",&k,&n,&m);
    	for(re int i=1,u,v,opt;i<=k;i++){
    		scanf("%d%d%d",&u,&v,&opt);
    		h[u].push_back((node){opt,i,u,v});
    		l[v].push_back((node){opt,i,u,v});
    	}
    	for(re int i=1;i<=n;i++){
    		re int N=h[i].size();
    		for(re int j=0;j<N;j++){
    			node t=h[i][j];
    			if(t.opt==1){
    				for(re int p=0;p<N;p++){
    					if(t.id==h[i][p].id) continue;
    					add(t.id,h[i][p].id);
    				}
    			}else if(t.opt==2){
    				re int M=l[t.y].size();
    				for(re int p=0;p<M;p++){
    					if(t.id==l[t.y][p].id) continue;
    					add(t.id,l[t.y][p].id);
    				}
    			}else{
    				for(re int p=max(1,t.x-1);p<=min(n,t.x+1);p++){
    					re int r=h[p].size();
    					for(re int q=0;q<r;q++){
    						if(h[p][q].id==t.id) continue;
    						if(abs(t.y-h[p][q].y)>1) continue;
    						add(t.id,h[p][q].id);
    					}
    				}
    			}
    		}
    	}
    	for(re int i=1;i<=k;i++){
    		if(!dfn[i]) tarjan(i);
    	}
    	for(re int i=1;i<=k;i++){
    		for(re int j=head[i];j;j=e[j].nxt){
    			re int y=e[j].to;
    			if(belong[y]!=belong[i]){
    				ADD(belong[i],belong[y]);
    				in_deg[belong[y]]++;
    			}
    		}
    	}
    	for(re int i=1;i<=tot;i++){
    		res[i]=siz[i];
    		if(!in_deg[i]) q.push(i);
    	}
    	while(!q.empty()){
    		re int x=q.front();
    		q.pop();
    		in_deg[x]--;
    		for(re int i=pre[x];i;i=nxt[i]){
    			re int y=to[i];
    			in_deg[y]--;
    			res[y]=max(res[y],res[x]+siz[y]);
    			ans=max(res[y],ans);
    			if(!in_deg[y]) q.push(y);
    		}
    	}
        //for(re int i=1;i<=tot;i++)
    	//	ans=max(res[i],ans);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    .Net Core小技巧
    调用Kubernetes API操作Kubernetes
    在CentOS 7+ 安装Kubernetes入门(单Master)
    Linux命令行基础
    使用wireshark学习TCP
    Redis原子性写入HASH结构数据并设置过期时间
    Vue使用小结
    JAVA & .NET创建对象构造函数调用顺序
    .NET 中的序列化 & 反序列化
    ASP.NET Core中使用Graylog记录日志
  • 原文地址:https://www.cnblogs.com/Juve/p/11372389.html
Copyright © 2011-2022 走看看