zoukankan      html  css  js  c++  java
  • 【CSP-S 2019模拟】题解

    T1:

    相当于是一个dp of dpdp of dp,第二维背包只用存前kk项即可

    看起来像2knk2^knk
    但实际上有用状态很少

    #include<bits/stdc++.h>
    using  namespace std;
    #define re register
    #define pb push_back
    #define cs const
    #define ll long long
    #define pii pair<int,int>
    #define fi first
    #define se second
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int mod=998244353;
    inline int add(int a,int b){a+=b-mod;return a+(a>>31&mod);}
    inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
    inline int mul(int a,int b){static ll r;r=1ll*a*b;return r>=mod?r%mod:r;}
    inline void Add(int &a,int b){a+=b-mod,a+=a>>31&mod;}
    inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
    inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod?r%mod:r);}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    cs int N=21,M=(1<<20)+5;
    int n,k,l,sta,lim;
    int f[N][M];
    int main(){
    	n=read(),k=read(),l=read();
    	sta=(1<<k)-1,lim=min(k-1,l);
    	f[0][1]=1;
    	for(int i=1;i<=n;i++){
    		for(int s=0;s<=sta;s++)if(f[i-1][s]){
    			for(int j=0;j<=lim;j++)if(!((s<<j)&(1<<k))){
    				Add(f[i][((s<<j)|s)&sta],f[i-1][s]);
    			}
    			if(l>k){
    				Add(f[i][s],mul(f[i-1][s],(l-k)%mod));
    			}
    		}
    	}
    	int res=0;
    	for(int s=0;s<=sta;s++)Add(res,f[n][s]);
    	cout<<dec(ksm(add(l,1),n),res);
    }
    

    T2:

    把权值排序后一个一个加,询问子树补集即可

    结果脑抽给自己多套了一个loglog

    #include<bits/stdc++.h>
    using  namespace std;
    #define re register
    #define pb push_back
    #define cs const
    #define ll long long
    #define pii pair<int,int>
    #define fi first
    #define se second
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    cs int N=500005;
    char xxx;
    int dfn,siz[N],son[N],fa[N],top[N],dep[N],in[N],out[N],idx[N];
    vector<int> e[N];
    int n,rt,val[N],a[N],s[N];
    void dfs1(int u){
    	siz[u]=1;
    	for(int i=0,v;i<e[u].size();i++){
    		v=e[u][i];
    		if(v==fa[u])continue;
    		fa[v]=u,dep[v]=dep[u]+1;
    		dfs1(v),siz[u]+=siz[v];
    		if(siz[v]>siz[son[u]])son[u]=v;
    	}
    }
    void dfs2(int u,int tp){
    	in[u]=++dfn,idx[dfn]=u,top[u]=tp;
    	if(son[u])dfs2(son[u],tp);
    	for(int i=0,v;i<e[u].size();i++){
    		v=e[u][i];
    		if(v==fa[u]||v==son[u])continue;
    		dfs2(v,v);
    	}
    	out[u]=dfn;
    }
    pii divi[N];
    int tot,ans[N];
    vector<int>nod[5000005];
    namespace Seg{
    	int s[N<<2];
    	#define lc (u<<1)
    	#define rc ((u<<1)|1)
    	#define mid ((l+r)>>1)
    	inline void pushup(int u){
    		s[u]=s[lc]|s[rc];
    	}
    	void update(int u,int l,int r,int p,int k){
    		if(l==r){s[u]=k;return;}
    		if(p<=mid)update(lc,l,mid,p,k);
    		else update(rc,mid+1,r,p,k);
    		pushup(u);
    	}
    	int query(int u,int l,int r,int st,int des){
    		if(st>des)return 0;
    		if(st<=l&&r<=des)return s[u];
    		int res=0;
    		if(st<=mid)res|=query(lc,l,mid,st,des);
    		if(mid<des)res|=query(rc,mid+1,r,st,des);
    		return res;
    	}
    }
    char yyy;
    int main(){ int size=40<<20;//40M
        //__asm__ ("movl  %0, %%esp
    "::"r"((char*)malloc(size)+size));//调试用这个 
        __asm__ ("movq %0,%%rsp
    "::"r"((char*)malloc(size)+size));//提交用这个 
    
    	n=read(),rt=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		e[u].pb(v),e[v].pb(u);
    	}
    	for(int i=1;i<=n;i++)a[i]=read();
    	dfs1(rt),dfs2(rt,rt);
    	for(int i=1;i<=n;i++)s[i]=s[i-1]+a[idx[i]];
    	for(int i=1;i<=n;i++)val[i]=s[out[i]]-s[in[i]-1],assert(val[i]!=0);
    	for(int i=1;i<=n;i++)nod[val[i]].pb(i);
    	for(int i=1;i<=s[n];i++)if(nod[i].size()){
    		for(int j=0;j<nod[i].size();j++){
    			int u=nod[i][j],res=0;
    			if(in[u]>1)res|=Seg::query(1,1,n,1,in[u]-1);
    			if(out[u]<n)res|=Seg::query(1,1,n,out[u]+1,n);
    			ans[u]=res;
    		}
    		for(int j=0;j<nod[i].size();j++){
    			int u=nod[i][j];
    			Seg::update(1,1,n,in[u],val[u]);
    		}
    	}
    	for(int i=1;i<=n;i++)cout<<ans[i]<<" ";exit(0);//必须用exit 
    }
    
    

    T3:

    5050~??的轮廓线写挂没调出来

    建图还是挺妙的

    考虑把方向相同的时候看做减少了valval,那就是让直的最少

    先把整个图黑白染色
    于是相邻连边可以看做都是从黑点流到白点
    那么显然的一个条件就是最后黑白点数量要相同
    于是起点u(cap=2,val=0) ightarrow u(cap=2,val=0)
    每个点再建两个方向点,分别表示像上下,左右
    uu向方向点连cap=1,val=0cap=1,val=0的边
    方向点之间互相连cap=1,val=Valcap=1,val=Val的边
    这样如果方向相同的话就会产生valval的代价
    方向点再向对于的白点连边
    白点类似的连向终点就可以跑最小费用最大流了

    #include<bits/stdc++.h>
    using  namespace std;
    #define re register
    #define pb push_back
    #define cs const
    #define ll long long
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define bg begin
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=50005,inf=1e9;
    int str,des,tot;
    namespace Flow{
    	struct edge{
    		int v,cap,val,r;
    		edge(int a=0,int b=0,int c=0,int d=0):v(a),cap(b),val(c),r(d){}
    	};
    	vector<edge> e[N];
    	typedef vector<edge>::iterator It;
    	It tp[N];
    	inline void add(int u,int v,int w,int c){
    		e[u].pb(edge(v,w,c,e[v].size()));
    		e[v].pb(edge(u,0,-c,e[u].size()-1));
    	}
    	int mxflow,mncost;
    	int dis[N],vis[N];
    	int q[500005],hd,tl;
    	inline bool spfa(){
    		memset(dis,127/3,sizeof(int)*(tot+1));
    		dis[str]=0;q[hd=tl=1]=str;
    		while(hd<=tl){
    			int u=q[hd++];vis[u]=0;
    			for(edge &x:e[u]){
    				if(dis[x.v]>dis[u]+x.val&&x.cap>0){
    					dis[x.v]=dis[u]+x.val;
    					if(!vis[x.v]){
    						vis[x.v]=1;
    						if(dis[x.v]<dis[q[hd]])q[--hd]=x.v;
    						else q[++tl]=x.v;
    					}
    				}
    			}
    		}
    		return dis[des]<dis[0];
    	}
    	int dfs(int u,int flow){
    		if(u==des)return flow;
    		vis[u]=1;int res=0;
    		for(It &it=tp[u];it!=e[u].end();it++){
    			if(!vis[it->v]&&dis[it->v]==dis[u]+it->val&&it->cap>0){
    				int now=dfs(it->v,min(it->cap,flow-res));
    				res+=now,it->cap-=now,e[it->v][it->r].cap+=now,mncost+=now*it->val;
    				if(res==flow)break;
    			}
    		}
    		vis[u]=0;
    		return res;
    	}
    	inline void mcmf(){
    		while(spfa()){
    			for(int i=1;i<=tot;i++)tp[i]=e[i].bg();
    			mxflow+=dfs(str,inf);
    		}
    	}
    }
    int n,m,cnt,num,all;
    int a[155][55],val[155][55],pos[155][55][3];
    inline bool ok(int x,int y){
    	return !a[x][y]&&(1<=x&&x<=n&&1<=y&&y<=m);
    }
    int main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#endif
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)
    	a[i][j]=read();
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)
    	val[i][j]=read();
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)if(!a[i][j])pos[i][j][0]=++tot,pos[i][j][1]=++tot,pos[i][j][2]=++tot,all+=val[i][j];
    	str=++tot,des=++tot;
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)
    	if(!a[i][j]){
    		if((i+j)&1){
    			num+=2,cnt++;
    			Flow::add(str,pos[i][j][0],2,0),Flow::add(pos[i][j][0],pos[i][j][1],1,0),Flow::add(pos[i][j][0],pos[i][j][2],1,0);
    			Flow::add(pos[i][j][1],pos[i][j][2],1,val[i][j]),Flow::add(pos[i][j][2],pos[i][j][1],1,val[i][j]);
    			if(ok(i-1,j))Flow::add(pos[i][j][1],pos[i-1][j][1],1,0);
    			if(ok(i+1,j))Flow::add(pos[i][j][1],pos[i+1][j][1],1,0);
    			if(ok(i,j-1))Flow::add(pos[i][j][2],pos[i][j-1][2],1,0);
    			if(ok(i,j+1))Flow::add(pos[i][j][2],pos[i][j+1][2],1,0);
    		}
    		else{
    			cnt--;
    			Flow::add(pos[i][j][0],des,2,0),Flow::add(pos[i][j][1],pos[i][j][0],1,0),Flow::add(pos[i][j][2],pos[i][j][0],1,0);
    			Flow::add(pos[i][j][1],pos[i][j][2],1,val[i][j]),Flow::add(pos[i][j][2],pos[i][j][1],1,val[i][j]);
    		}
    	}
    	if(cnt)return puts("-1"),0;
    	Flow::mcmf();
    	if(Flow::mxflow<num)return puts("-1"),0;
    	cout<<all-Flow::mncost<<'
    ';
    }
    
  • 相关阅读:
    如何修改注册表立刻生效【搜藏】
    c#怎样让picturebox出现滚动条【搜藏】
    c#怎样让程序运行出错仍继续执行【原】
    marquee标签里文本的自动换行【搜藏】
    关于HyperLink的NavigateUrl属性的链接地址带参数出错的问题【整理】
    C#程序获得星期【整理】
    sql分别获取年/月/日 函数【搜藏】
    获取本周属于本年度第几周【搜藏】
    关于ref 和 out 关键字【整理】
    hdu 1823 Luck and Love
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328379.html
Copyright © 2011-2022 走看看