• CQOI2017 部分题解


    部分题解是指没写那道算几。

    BZOJ上目前没有day2的题面D2T2的图。

    BZOJ4813 小Q的棋盘

    显然可以$O(n^2)$DP,然而可以$O(n)$贪心:只有一条从根出发的一条链上的边可以只经过一次,其他边如果被经过则必须经过两次,且次数没用完时一定可以用来经过没被经过的边,那么只用枚举那条链的端点。

    感觉和SCOI D1T1神似:$O(n^2)$树形DP显然,然而可以$O(n)$贪心。只不过SCOI DP过不了

    #include<stdio.h>
    struct node;
    typedef struct node edge;
    struct node{
    	int v;
    	edge*s;
    }e[198];
    edge*l=e,*h[100];
    void ins(int u,int v){
    	edge s={v,h[u]};
    	*(h[u]=l++)=s;
    }
    int n,m,u,v,a,d[100];
    void dfs(int u,int j){
    	if(m>=d[u]){
    		if(a<d[u]+m+2>>1)
    			a=d[u]+m+2>>1;
    		for(edge*i=h[u];i;i=i->s)
    			if(i->v!=j)
    				d[i->v]=d[u]+1,dfs(i->v,u);
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<n;++i)
    		scanf("%d%d",&u,&v),ins(u,v),ins(v,u);
    	dfs(0,0);
    	printf("%d
    ",a<n?a:n);
    }
    

    BZOJ4815 小Q的表格

    设$gcd(a,b)=d$,则$f(a,b)=frac{ab}{d^2}f(d,d)$。

    egin{align*}&sum_{d=1}^nf(d,d)sum_{i=1}^{leftlfloorfrac nd ight floor}sum_{j=1}^{leftlfloorfrac nd ight floor}ij[(i,j)=1]\=&sum_{d=1}^nf(d,d)sum_{i=1}^{leftlfloorfrac nd ight floor}i^2varphi(i)end{align*}

    分块维护一下$f(d,d)$就好了,复杂度$O(n+msqrt{n})$。

    #include<cstdio>
    #include<cmath>
    typedef unsigned long long ll;
    const int p=1e9+7;
    const int N=4e6+5;
    int gcd(int a,int b){
    	return b?gcd(b,a%b):a;
    }
    inline int foo(int x){
    	return x<p?x:x-p;
    }
    inline int bar(int x){
    	return x<0?x+p:x;
    }
    inline void inc(int&x,int y){
    	x=foo(x+y);
    }
    typedef int arr[N];
    int m,n,nb,bs,np;
    arr b,c1,c2,c3,c4,f,q;
    inline int ask(int x){
    	return x>bs?foo(c3[x]+c4[b[x]]):c3[x];
    }
    void cov(int x,int y){
    	int d=bar(y-bar(ask(x)-ask(x-1)));
    	for(int i=x;i<=c2[b[x]];++i)
    		inc(c3[i],d);
    	for(int i=b[x]+1;i<=nb-1;++i)
    		inc(c4[i],d);
    }
    int main(){
    	scanf("%d%d",&m,&n);
    	bs=sqrt(n+.5)*3/2;
    	for(int i=1;i<=n;++i)
    		b[i]=(i-1)/bs;
    	nb=b[n]+1;
    	for(int i=1;i<=n;++i)
    		c2[b[i]]=i;
    	for(int i=n;i>=1;--i)
    		c1[b[i]]=i;
    	for(int i=1;i<=n;++i){
    		c3[i]=(ll)i*i%p;
    		inc(c4[b[i]+1],c3[i]);
    		if(i!=c1[b[i]])
    			inc(c3[i],c3[i-1]);
    	}
    	for(int i=1;i<nb;++i)
    		inc(c4[i],c4[i-1]);
    	f[1]=1;
    	for(int i=2;i<=n;++i){
    		if(!f[i]){
    			f[i]=(ll)i*i%p*(i-1)%p;
    			q[np++]=i;
    		}
    		for(int*j=q;;++j){
    			if(i**j>n)break;
    			if(i%*j==0){
    				f[i**j]=(ll)*j**j**j%p*f[i]%p;
    				break;
    			}
    			f[i**j]=(ll)f[i]*f[*j]%p;
    		}
    	}
    	for(int i=2;i<=n;++i)
    		inc(f[i],f[i-1]);
    	while(m--){
    		int x,y;
    		ll z;
    		scanf("%d%d%lld%d",&x,&y,&z,&n);
    		int d=gcd(x,y);
    		cov(d,z/(x/d)/(y/d)%p);
    		int i=1,s=0;
    		while(i<=n){
    			int j=n/(n/i);
    			s=(s+(ll)bar(f[j]-f[i-1])*ask(n/i))%p;
    			i=j+1;
    		}
    		printf("%d
    ",s);
    	}
    }
    

    BZOJ4822 老C的任务

    签到题。

    和SCOI D2T1神似:NOIP难度以下签到题。只不过SCOI有人被卡常数T了5分

    #include<bits/stdc++.h>
    #define lb lower_bound
    #define ub upper_bound
    #define pb push_back
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    struct node{
    	node*i,*j;
    	ll s;
    }e[N*20];
    node*l=e,*r[N];
    void ins(int z,int y,node**o){
    	for(int i=16;~i;--i){
    		*++l=**o,*o=l;
    		if(y>>i&1)o=&(*o)->j;
    		else
    			(*o)->s+=z,o=&(*o)->i;
    	}
    }
    ll ask(int y,node*s,node*t){
    	ll z=0;
    	for(int i=16;~i;--i)
    		if(~y>>i&1)s=s->i,t=t->i;
    		else
    			z+=t->s-s->s,s=s->j,t=t->j;
    	return z;
    }
    int n,m,s,t,u,v,x[N],y[N],z[N],a[N],b[N];
    vector<int>c[N];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<n;++i)
    		scanf("%d%d%d",x+i,y+i,z+i),a[i]=x[i],b[i]=y[i];
    	sort(a,a+n);
    	sort(b,b+n);
    	for(int i=0;i<n;++i)
    		c[lb(a,a+n,x[i])-a+1].pb(i),y[i]=lb(b,b+n,y[i])-b+1;
    	*(*r=e)=(node){e,e};
    	for(int i=1;i<=n;++i){
    		r[i]=r[i-1];
    		for(int j=0;j<c[i].size();++j){
    			int k=c[i][j];
    			ins(z[k],y[k],r+i);
    		}
    	}
    	while(m--){
    		scanf("%d%d%d%d",&s,&t,&u,&v);
    		s=lb(a,a+n,s)-a+1;
    		t=lb(b,b+n,t)-b+1;
    		u=ub(a,a+n,u)-a;
    		v=ub(b,b+n,v)-b;
    		printf("%lld
    ",ask(v+1,r[s-1],r[u])-ask(t,r[s-1],r[u]));
    	}
    }
    

    BZOJ4823 老C的方块

    设特殊边两边的方块为灰色,这两个方块的其他相邻方块分别为黑色和白色,可以将整个棋盘染色。当两个灰色方块同时存在时,相邻的其他方块只能有一种颜色,那么容易建立最小割模型,S向所有黑色方块连边,所有白色方块向T连边,容量为权值;灰色方块与相邻的黑色或白色方块连边,容量为无穷大;两个灰色方块之间连边,容量为两个方块权值的较小值。

    #include<bits/stdc++.h>
    using namespace std;
    const int dx[]={-1,1,0,0};
    const int dy[]={0,0,-1,1};
    const int N=1e5+5;
    const int inf=1061109567;
    struct edge{
    	int v,c;
    	edge*s;
    }e[N*8];
    edge*l=e,*h1[N],*h2[N];
    void ins(int u,int v,int c){
    	edge a={v,c,h1[u]};
    	edge b={u,0,h1[v]};
    	*(h1[u]=l++)=a;
    	*(h1[v]=l++)=b;
    }
    int s1,s2,d[N],q[N];
    int dfs(int u,int c){
    	if(u==s2)return c;
    	int f=0;
    	for(edge*&i=h2[u];i;i=i->s)
    		if(d[u]+1==d[i->v]&&i->c){
    			int v=dfs(i->v,min(c-f,i->c));
    			i->c-=v;
    			e[i-e^1].c+=v;
    			f+=v;
    			if(f==c)break;
    		}
    	if(!f)d[u]=-1;
    	return f;
    }
    int bfs(){
    	int f=0;
    	for(;;f+=dfs(s1,inf)){
    		fill(d,d+s2+1,-1);
    		d[q[0]=s1]=0;
    		for(int a=0,b=0;a<=b;++a){
    			int u=q[a];
    			for(edge*i=h2[u]=h1[u];i;i=i->s)
    				if(!~d[i->v]&&i->c)
    					d[q[++b]=i->v]=d[u]+1;
    		}
    		if(!~d[s2])return f;
    	}
    }
    int jud(int x,int y){
    	int a=x&1,b=y&3;
    	return a&&!b||!a&&b==1?0:a&&b==3||!a&&b==2?1:a&&b==1||!a&&!b?2:3;
    }
    map<int,int>f[N];
    int n,x[N],y[N],w[N];
    int main(){
    	scanf("%*d%*d%d",&n),s1=n,s2=n+1;
    	for(int i=0;i<n;++i){
    		scanf("%d%d%d",y+i,x+i,w+i);
    		f[x[i]][y[i]]=i;
    	}
    	for(int i=0;i<n;++i){
    		int x=::x[i],y=::y[i];
    		if(!jud(x,y))
    			ins(s1,i,w[i]);
    		else if(jud(x,y)==1)
    			ins(i,s2,w[i]);
    		else
    			for(int j=0;j<4;++j){
    				int nx=x+dx[j],ny=y+dy[j];
    				int z=jud(nx,ny);
    				map<int,int>::iterator k=f[nx].find(ny);
    				if(k!=f[nx].end())
    					if(!z)
    						ins(k->second,i,inf);
    					else if(z==1)
    						ins(i,k->second,inf);
    					else if(z==3)
    						ins(i,k->second,min(w[i],w[k->second]));
    			}
    	}
    	printf("%d
    ",bfs());
    }
    

    BZOJ4824 老C的键盘

    把BZOJ3167粘过来改改就好了。

    #include<algorithm>
    #include<cstdio>
    using namespace std;
    typedef unsigned long long ll;
    const int p=1e9+7;
    const int N=100;
    ll f[N][N],g[N],c[N][N];
    int n,e[N][N],r[N];
    void dfs(int u,int l){
    	r[u]=f[u][0]=1;
    	for(int v=0;v<n;++v)
    		if(e[u][v]&&v!=l){
    			dfs(v,u);
    			fill(g,g+n,0);
    			for(int i=0;i<r[u];++i)
    				if(~e[u][v])
    					for(int j=1;j<=r[v];++j)
    						(g[i+j]+=f[u][i]*f[v][j-1]%p*c[i+j][j]%p*c[r[u]+r[v]-i-j-1][r[v]-j])%=p;
    				else
    					for(int j=0;j<r[v];++j)
    						(g[i+j]+=f[u][i]*f[v][j]%p*c[i+j][j]%p*c[r[u]+r[v]-i-j-1][r[v]-j])%=p;
    			copy(g,g+n,f[u]);
    			r[u]+=r[v];
    		}
    	if(~e[u][l])
    		for(int i=r[u]-2;~i;--i)
    			(f[u][i]+=f[u][i+1])%=p;
    	else
    		for(int i=1;i<r[u];++i)
    			(f[u][i]+=f[u][i-1])%=p;
    }
    char w[N];
    int main(){
    	for(int i=0;i<N;++i){
    		c[i][0]=1;
    		for(int j=1;j<N;++j)
    			c[i][j]=(c[i-1][j]+c[i-1][j-1])%p;
    	}
    	scanf("%d%s",&n,w);
    	for(int i=1;i<n;++i){
    		int u=(i+1)/2-1;
    		if(w[i-1]=='<')
    			e[i][u]=1,e[u][i]=-1;
    		else
    			e[u][i]=1,e[i][u]=-1;
    	}
    	dfs(0,0);
    	printf("%d
    ",f[0][0]);
    }
    
  • 相关阅读:
    OC-为何用copy修饰block
    OC-RunLoop运行循环
    苹果审核之遇到IPV6问题被拒的解决方法
    LeetCode学习_day1:原地算法
    OC-加载h5富文本的代码,并计算高度
    OC-bug: Undefined symbols for architecture i386: "_OBJC_CLASS_$_JPUSHRegisterEntity", referenced from:
    了解iOS各个版本新特性总结
    iOS 快速打包方法
    iOS tableView侧滑删除的第三方控件
    Object_C 集成环信时,中文环境下不显示中文
  • 原文地址:https://www.cnblogs.com/f321dd/p/6716924.html
Copyright © 2020-2023  润新知