zoukankan      html  css  js  c++  java
  • SDOI2016 Round1 题解

    BZOJ4513 储能表

    数位DP,f[i][2][2][2]表示前i位,是否卡n的上界,是否卡m的上界,是否卡k的下界,枚举每一维的下一位直接转移。

    #include<cstdio>
    #include<cstring>
    typedef unsigned u32;
    typedef long long ll;
    ll x,y,z;
    int p,q;
    u32 f[61][2][2][2][2];
    int main(){
    	scanf("%d",&q);
    	while(q--){
    		scanf("%lld%lld%lld%d",&x,&y,&z,&p);
    		memset(f,0,sizeof f);
    		f[60][1][1][1][0]=1;
    		for(int i=59;~i;--i)
    			for(int j=1;~j;--j)
    				for(int k=1;~k;--k)
    					for(int l=1;~l;--l)
    						for(int a=j?x>>i&1:1;~a;--a)
    							for(int b=k?y>>i&1:1;~b;--b)
    								if(!l||(z>>i&1)<=(a^b)){
    									u32*s=f[i][j&(x>>i&1)==a][k&(y>>i&1)==b][l&(z>>i&1)==(a^b)],*t=f[i+1][j][k][l];
    									(s[0]+=t[0])%=p,(s[1]+=t[1]*2+(a^b)*t[0])%=p;
    								}
    		printf("%lld
    ",(1[****f]-z%p******f%p+p)%p);
    	}
    }
    

    BZOJ4514 数字配对

    若$j$是$i$的倍数且$Omega(j)-1=Omega(i)$则$i$,$j$可以配对,其中$Omega(i)$表示$i$的质因子指数和。按$Omega(i)$的奇偶性建二分图,跑费用流。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll inf=-1e18;
    const int N=205;
    void eq1(int&a,int b){a=b<a?b:a;}
    struct edge{
    	int v,c;ll w;edge*s;
    }e[N*N];
    edge*p=e,*h[N];
    void ins(int u,int v,ll w,int c){
    	edge s={v,c,w,h[u]};
    	edge t={u,0,-w,h[v]};
    	*(h[u]=p++)=s;
    	*(h[v]=p++)=t;
    }
    int n,s,t,q[N*N];
    typedef int arr[N];
    arr a,b,c,d,f,z;
    ll r[N];
    int dfs(int u,int c){
    	if(u==t)return c;
    	int f=0;
    	for(edge*i=h[u];i;i=i->s)
    		if(r[u]-i->w==r[i->v]&&d[u]-1==d[i->v]&&i->c){
    			int j=dfs(i->v,min(c-f,i->c));
    			i->c-=j,e[i-e^1].c+=j,f+=j;
    			if(f==c)break;
    		}
    	if(!f)d[u]=-1;
    	return f;
    }
    int spfa(){
    	int f=0;
    	ll c=0;
    	while(1){
    		fill(r+s,r+t,inf);
    		q[0]=t;
    		for(int a=0,b=0;a<=b;++a){
    			int u=q[a];
    			z[u]=0;
    			for(edge*i=h[u];i;i=i->s)
    				if(r[i->v]<r[u]-i->w&&e[i-e^1].c){
    					r[i->v]=r[u]-i->w;
    					d[i->v]=d[u]+1;
    					if(!z[i->v]++)q[++b]=i->v;
    				}
    		}
    		if(r[s]==inf)return f;
    		while(1){
    			int j=dfs(s,1e9);
    			if(!j)break;
    			if(r[s]<0&&c/-r[s]<=j){
    				f+=c/-r[s],c%=-r[s];
    				break;
    			}
    			f+=j,c+=j*r[s];
    		}
    	}
    }
    int main(){
    	scanf("%d",&n),t=n+1;
    	for(int i=1;i<=n;++i)
    		scanf("%d",a+i);
    	for(int i=1;i<=n;++i)
    		scanf("%d",b+i);
    	for(int i=1;i<=n;++i)
    		scanf("%d",c+i);
    	for(int i=1;i<=n;++i){
    		int j=a[i];
    		for(int d=2;d*d<=j;++d)
    			for(;j%d==0;j/=d)++f[i];
    		f[i]+=j!=1;
    	}
    	for(int i=1;i<=n;++i)
    		if(f[i]&1){
    			ins(s,i,0,b[i]);
    			for(int j=1;j<=n;++j)
    				if(abs(f[i]-f[j])==1&&max(a[i],a[j])%min(a[i],a[j])==0)
    					ins(i,j,(ll)c[i]*c[j],1e9);
    		}else
    			ins(i,t,0,b[i]);
    	printf("%d
    ",spfa());
    }
    

    BZOJ4515 游戏

    哪个SB把李超线段树出到树上的……修改拆成两条链,设$t$是$s$的祖先,那么$x$上的数字为$a(d_s-d_x)+b$,所以可以统一插入斜率为$-a$,截距为$ad_s+b$的线段。

    #include<bits/stdc++.h>
    #define I (i+j+2>>1)
    #define J (i+j>>1)
    #define P (k<<1)
    #define S (k<<1^1)
    using namespace std;
    template<class T>
    void eq1(T&a,T b){a=b<a?b:a;}
    typedef long long ll;
    const int N=1e5+5;
    int n,n2;
    typedef int arr[N];
    arr d1,f1,f2,f3,f4,f5,f6;
    ll d2[N],z[N*4];
    struct tag{
    	int s;ll t;
    	ll operator()(int i){
    		return s*d2[f6[i]]+t;
    	}
    }c[N*4];
    void ins(tag f,int s,int t,int i,int j,int k){
    	if(s<=i&&j<=t){
    		if(i==j){
    			if(f(i)<c[k](i))c[k]=f;
    		}else
    			if(f(i)<c[k](i))
    				if(f(j)<c[k](j))c[k]=f;
    				else
    					if(f(J)>c[k](J))ins(f,s,t,i,J,P);
    					else
    						ins(c[k],s,t,I,j,S),c[k]=f;
    			else
    				if(f(j)<c[k](j))
    					if(f(I)>c[k](I))ins(f,s,t,I,j,S);
    					else
    						ins(c[k],s,t,i,J,P),c[k]=f;
    		eq1(z[k],c[k](i));
    		eq1(z[k],c[k](j));
    	}else{
    		if(s<I)ins(f,s,t,i,J,P);
    		if(t>J)ins(f,s,t,I,j,S);
    		eq1(z[k],z[P]);
    		eq1(z[k],z[S]);
    	}
    }
    ll ask(int s,int t,int i,int j,int k){
    	if(s==i&&j==t)return z[k];
    	ll y=min(c[k](s),c[k](t));
    	if(t<I)return min(y,ask(s,t,i,J,P));
    	if(s>J)return min(y,ask(s,t,I,j,S));
    	return min(y,min(ask(s,J,i,J,P),ask(I,t,I,j,S)));
    }
    struct edge{
    	int v,w;edge*s;
    }e[N*2];
    edge*x=e,*h[N];
    void ins(int u,int v,int w){
    	edge s={v,w,h[u]};
    	*(h[u]=x++)=s;
    }
    void dfs1(int u){
    	f1[u]=1;
    	for(edge*i=h[u];i;i=i->s)
    		if(i->v!=f2[u]){
    			f2[i->v]=u,d1[i->v]=d1[u]+1,d2[i->v]=d2[u]+i->w;
    			dfs1(i->v);
    			f1[u]+=f1[i->v];
    			if(f1[i->v]>f1[f3[u]])
    				f3[u]=i->v;
    		}
    }
    void dfs2(int u,int v){
    	f4[f6[f5[u]=++n2]=u]=v;
    	if(f3[u])dfs2(f3[u],v);
    	for(edge*i=h[u];i;i=i->s)
    		if(i->v!=f2[u]&&i->v!=f3[u])
    			dfs2(i->v,i->v);
    }
    int lca(int s,int t){
    	while(f4[s]!=f4[t]){
    		if(d1[f4[s]]<d1[f4[t]])swap(s,t);
    		s=f2[f4[s]];
    	}
    	return d1[s]<d1[t]?s:t;
    }
    void ins(tag f,int s,int t){
    	while(f4[s]!=f4[t]){
    		ins(f,f5[f4[s]],f5[s],1,n,1);
    		s=f2[f4[s]];
    	}
    	ins(f,f5[t],f5[s],1,n,1);
    }
    int main(){
    	int m,w,u,v,s,t;
    	scanf("%d%d",&n,&m);
    	for(int i=2;i<=n;++i){
    		scanf("%d%d%d",&u,&v,&w);
    		ins(u,v,w),ins(v,u,w);
    	}
    	dfs1(1),dfs2(1,1);
    	for(int i=1;i<N*4;++i)
    		c[i].t=z[i]=123456789123456789;
    	while(m--){
    		scanf("%d%d%d",&w,&s,&t);
    		if(w==1){
    			scanf("%d%d",&u,&v);
    			int l=lca(s,t);
    			tag f1={-u,u*d2[s]+v},f2={u,u*d2[s]-u*d2[l]*2+v};
    			ins(f1,s,l);
    			ins(f2,t,l);
    		}else{
    			ll y=1e18;
    			while(f4[s]!=f4[t]){
    				if(d1[f4[s]]<d1[f4[t]])
    					swap(s,t);
    				y=min(y,ask(f5[f4[s]],f5[s],1,n,1));
    				s=f2[f4[s]];
    			}
    			if(d1[s]<d1[t])swap(s,t);
    			y=min(y,ask(f5[t],f5[s],1,n,1));
    			printf("%lld
    ",y);
    		}
    	}
    }
    

    BZOJ4516 生成魔咒

    BZOJ4517 排列计数

    裸的错排……

    #include<cstdio>
    typedef long long ll;
    const int p=1e9+7;
    const int N=1e6+5;
    int q,n,m;
    ll f1[N],f2[N],f3[N],f4[N];
    int main(){
    	f1[1]=f2[0]=f3[0]=f4[0]=1;
    	for(int i=2;i<N;++i)
    		f1[i]=f1[p%i]*(p-p/i)%p,f4[i]=(i-1)*(f4[i-1]+f4[i-2])%p;
    	for(int i=1;i<N;++i)
    		f2[i]=f2[i-1]*i%p,f3[i]=f3[i-1]*f1[i]%p;
    	scanf("%d",&q);
    	while(q--){
    		scanf("%d%d",&n,&m);
    		printf("%d
    ",f2[n]*f3[m]%p*f3[n-m]%p*f4[n-m]%p);
    	}
    }
    

    BZOJ4518 征途

    斜率优化,设$s$为前缀和,容易推出$f_j+(m+1)s_j^2=2ms_is_j+f_i-(m-1)s_i^2$,横坐标和斜率都单调,单调队列维护即可。

    #include<cstdio>
    typedef long long ll;
    const int N=3005;
    int n,m,a,b,q[N];
    ll s[N],f[N],g[N];
    double cal1(int i,int j){
    	return(f[i]-f[j]+(m+1)*(s[i]*s[i]-s[j]*s[j]))/1./(s[i]-s[j]);
    }
    ll cal2(int j,int i){
    	return f[j]+(m-1)*s[i]*s[i]+(m+1)*s[j]*s[j]-m*s[i]*s[j]*2;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    		scanf("%lld",s+i),s[i]+=s[i-1],f[i]=1e18;
    	for(int z=1;z<=m;++z){
    		q[a=b=0]=z-1;
    		for(int i=z;i<=n;++i){
    			while(a<b&&cal2(q[a],i)>cal2(q[a+1],i))
    				++a;
    			g[i]=cal2(q[a],i);
    			while(a<b&&cal1(q[b],i)<cal1(q[b-1],i))
    				--b;
    			q[++b]=i;
    		}
    		for(int i=z;i<=n;++i)
    			f[i]=g[i];
    	}
    	printf("%lld
    ",f[n]);
    }
    
  • 相关阅读:
    day 06小结
    day 05小结
    day 05作业
    day 04作业
    day 03作业
    今日小结
    day 02小结
    hdu 4608 I-number(13多校#1 ,1009)
    zoj 2316 Matrix Multiplication(D)
    zoj 2316 Matrix Multiplication(2-D)
  • 原文地址:https://www.cnblogs.com/f321dd/p/6368405.html
Copyright © 2011-2022 走看看