SDOI2017 Round1 Day2 题解

T2好厉害啊……AK不了啦……不过要是SCOI考这套题就好了240保底。

BZOJ4819 新生舞会

模板题,分数规划+二分图最大权匹配。费用流跑得过,可以不用KM。

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef double flo;
const int inf=1e9;
const int N=205;
struct edge{
	int v,c;
	flo w;
}e[20400];
vector<int>h[N];
int l;
void ins(int u,int v,int c,flo w){
	edge a={v,c,w};
	h[u].pb(l);
	e[l++]=a;
	edge b={u,0,-w};
	h[v].pb(l);
	e[l++]=b;
}
flo d[N];
int s1,s2,q[N*N],vis[N],p[N];
bool spfa(){
	flo c=0;
	while(1){
		fill(d,d+s2+1,-inf);
		d[q[0]=s1]=0;
		for(int a=0,b=0;a<=b;++a){
			int u=q[a];
			vis[u]=0;
			for(int i=0;i<h[u].size();++i){
				edge*j=e+h[u][i];
				if(d[u]+j->w>d[j->v]&&j->c){
					d[j->v]=d[u]+j->w;
					p[j->v]=j-e;
					if(!vis[j->v]++)q[++b]=j->v;
				}
			}
		}
		if(d[s2]==-inf)
			return 1;
		int f=inf;
		for(int i=s2;i!=s1;i=e[p[i]^1].v)
			f=min(f,e[p[i]].c);
		c+=f*d[s2];
		if(c<0)return 0;
		for(int i=s2;i!=s1;i=e[p[i]^1].v){
			e[p[i]].c-=f;
			e[p[i]^1].c+=f;
		}
	}
}
int n,a[N][N],b[N][N];
bool jud(flo c){
	for(int i=s2;~i;--i)
		h[i].clear();
	l=0;
	for(int i=1;i<=n;++i){
		ins(s1,i,1,0);
		ins(i+n,s2,1,0);
		for(int j=1;j<=n;++j)
			ins(i,j+n,1,a[i][j]-c*b[i][j]);
	}
	return spfa();
}
int main(){
	scanf("%d",&n);
	s2=n*2+1;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			scanf("%d",a[i]+j);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			scanf("%d",b[i]+j);
	flo l=1e-4,r=1e4;
	while(r-l>1e-8){
		flo j=(l+r)/2;
		(jud(j)?l:r)=j;
	}
	printf("%.6f\n",l);
}

BZOJ4820 硬币游戏

设$f_i$为经过$i$的次数的期望。把所有非终止态记为一个状态$p$,考虑$p$加上一个人的串,可能直接到对应的终止态,也可能先到其他终止态(可能是自己),因此要减去其他终止态的贡献。比如终止态$x$、$y$的串分别为TTH、HTT,那么$p$+TTH可能是$y$+TH或$y$+H,因此$f_x=\frac18f_p-\frac34f_y$,因为$p$有$\frac18$的概率到$x$,其中到了$y$的话有$\frac34$的概率到$x$。可能先到其他终止态的情况也就是其他串的后缀匹配了当前串的前缀,可以用kmp计算。列出这些方程后高斯消元即可。

#include<bits/stdc++.h>
using std::swap;
typedef long double flo;
const int N=302;
int n,m,f[N];
char z[N][N];
flo c[N][N];
void piv(int i){
	int j=i;
	for(int k=i+1;k<=n;++k)
		if(fabs(c[k][i])>fabs(c[j][i]))j=k;
	for(int k=i;k<=n+1;++k)
		swap(c[i][k],c[j][k]);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;++i)
		scanf("%s",z[i]);
	f[0]=-1;
	for(int i=0;i<n;++i){
		int j=0,k=-1;
		while(j<m){
			while(~k&&z[i][j]!=z[i][k])k=f[k];
			f[++j]=++k;
		}
		for(int l=0;l<n;++l){
			j=k=0;
			while(j<m){
				while(~k&&z[l][j]!=z[i][k])k=f[k];
				++j,++k;
			}
			for(;k;k=f[k])
				c[i][l]+=pow(.5l,m-k);
		}
		c[i][n]=-pow(.5l,m);
		c[n][i]=1;
	}
	c[n][n+1]=1;
	for(int i=0;i<=n;++i){
		piv(i);
		for(int j=n+1;j>=i;--j)
			c[i][j]/=c[i][i];
		for(int j=0;j<=n;++j)
			if(i!=j)
				for(int k=n+1;k>=i;--k)
					c[j][k]-=c[j][i]*c[i][k];
	}
	for(int i=0;i<n;++i)
		printf("%.10f\n",double(c[i][n+1]));
}

BZOJ4821 相关分析

简单线段树,维护$\sum x$、$\sum y$、$\sum xy$、$\sum x^2$以及两种标记。

#include<cstdio>
#define P (k<<1)
#define S (P^1)
typedef long double flo;
const int N=1e5+5;
flo cal1(flo n){return n*(n-1)/2;}
flo cal2(flo n){return n*(n-1)*(n*2-1)/6;}
struct vec{flo a,b,c,d;};
vec operator+(vec a,vec b){
	vec c={
		a.a+b.a,a.b+b.b,a.c+b.c,a.d+b.d
	};
	return c;
}
struct node{
	int i,j,n;
	vec s;
	flo xd,yd,xc,yc;
	bool d,c;
	void upd1(flo x,flo y){
		if(!d)
			xd=x,yd=y,d=1;
		else
			xd+=x,yd+=y;
		s.c+=y*s.a+x*s.b+n*x*y;
		s.d+=x*s.a*2+n*x*x;
		s.a+=n*x;
		s.b+=n*y;
	}
	void upd2(flo x,flo y){
		xc=x,yc=y,c=1,d=0;
		flo a=x+i,b=y+i;
		s.a=n*a+cal1(n);
		s.b=n*b+cal1(n);
		s.c=n*a*b+cal1(n)*(a+b)+cal2(n);
		s.d=n*a*a+cal1(n)*a*2+cal2(n);
	}
}a[N*4];
void down(int k){
	if(a[k].c){
		a[P].upd2(a[k].xc,a[k].yc);
		a[S].upd2(a[k].xc,a[k].yc);
		a[k].c=0;
	}
	if(a[k].d){
		a[P].upd1(a[k].xd,a[k].yd);
		a[S].upd1(a[k].xd,a[k].yd);
		a[k].d=0;
	}
}
void upd1(int k){
	a[k].s=a[P].s+a[S].s;
}
void upd2(int k){
	a[k].i=a[P].i;
	a[k].j=a[S].j;
	a[k].n=a[P].n+a[S].n;
	upd1(k);
}
int f[N],g[N];
void pre(int i,int j,int k){
	if(i==j){
		flo x=f[i],y=g[i];
		a[k]=(node){i,j,1,x,y,x*y,x*x};
	}else{
		pre(i,i+j>>1,P);
		pre((i+j>>1)+1,j,S);
		upd2(k);
	}
}
void inc(flo x,flo y,int s,int t,int k){
	if(s<=a[k].i&&a[k].j<=t)
		a[k].upd1(x,y);
	else{
		down(k);
		if(s<a[S].i)inc(x,y,s,t,P);
		if(t>a[P].j)inc(x,y,s,t,S);
		upd1(k);
	}
}
void cov(flo x,flo y,int s,int t,int k){
	if(s<=a[k].i&&a[k].j<=t)
		a[k].upd2(x,y);
	else{
		down(k);
		if(s<a[S].i)cov(x,y,s,t,P);
		if(t>a[P].j)cov(x,y,s,t,S);
		upd1(k);
	}
}
vec ask(int s,int t,int k){
	if(s==a[k].i&&a[k].j==t)
		return a[k].s;
	down(k);
	return t<a[S].i?ask(s,t,P):s>a[P].j?ask(s,t,S):ask(s,a[P].j,P)+ask(a[S].i,t,S);
}
int main(){
	int n,m,o,s,t,x,y;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%d",f+i);
	for(int i=1;i<=n;++i)scanf("%d",g+i);
	pre(1,n,1);
	while(m--){
		scanf("%d%d%d",&o,&s,&t);
		if(o==1){
			vec v=ask(s,t,1);
			int n=t-s+1;
			printf("%.10f\n",double((v.c-v.a*v.b/n)/(v.d-v.a*v.a/n)));
		}else{
			scanf("%d%d",&x,&y);
			(o==2?inc:cov)(x,y,s,t,1);
		}
	}
}

  

时间: 2024-10-17 08:34:19

SDOI2017 Round1 Day2 题解的相关文章

SDOI2017 Round1 Day1 题解 (BZOJ4816 BZOJ4817 BZOJ4818)

不知道有几个AK的,除了出题人SB搬了个BZOJ3779以外,应该没什么因素阻碍AK吧.要是SCOI考这套题多好. BZOJ4816 数字表格 SB反演,推出$ans=\prod_{i=1}^nf^{\sum_{j=1}^{\left\lfloor\frac ni\right\rfloor}\mu(j)\left\lfloor\frac n{ij}\right\rfloor\left\lfloor\frac m{ij}\right\rfloor}(i)$,直接$O(n^{\frac34}+n^{

【BZOJ 4517】【SDOI 2016】Round1 Day2 T2 排列计数

本蒟蒻第一次没看题解A的题竟然是省选$Round1$ $Day2$ $T2$ 这道组合数学题. 考试时一开始以为是莫队,后来想到自己不会组合数的一些公式,便弃疗了去做第三题,,, 做完第三题后再回来看这道题,想到暴力算$组合数×错排$,我记得有一天晚上$Snayvals$问过我错排公式怎么推,但我并没有在意!!!幸亏我知道错排可以线性推出来,便开始用笔推错排公式.推了$30min$发现有计算机为什么不用!!!便打了一个表,很快就找出了规律$f[i]=(f[i-1]*f[i-2])*(i-1)$

NOI2014 DAY2 题解

当天下午3点拿到jcvb现场发来的数据,本地自测100+100+30=230. BUAA成绩60+60+30=150.sad story~ 动物园 zoo 既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]. 偌大的提示:kmp! 思路很简单,求出next数组,你会发现这是一棵树,求出根(0)~i路径上<i/2的元素有多少个. BIT nlogn? 多组数据会被卡.(ok多个log也能过的策爷!人家是策爷!) 我跟dzy说,类似单调栈..反正栈上搞搞就行.

二模Day2题解

小明搬家 题目描述 小明要搬家了,大家都来帮忙. 小明现在住在第N楼,总共K个人要把X个大箱子搬上N楼. 最开始X个箱子都在1楼,但是经过一段混乱的搬运已经乱掉了.最后大家发现这样混乱地搬运过程效率太低了,于是总结出了提高效率的方法. 大家的速度都是每分钟上(或下)一层楼.所有向上走的人手中都拿一个箱子,所有向下走的人手中都不拿箱子.到达第N层立刻放下箱子向下走,到达第1层立刻拿起箱子向上走.当一个人向上走,另一人向下走而在楼道里相遇时,向上走的人将手中的箱子交给另一人,两人同时反向.即原来拿箱

SDOI2017 R2 Day2

2018.4.29 Test 时间:7:30~11:30(实际没用多少) 实际得分:0+20+30=50 总结 LOJ总题目链接 T1 BZOJ.4912.[SDOI2017]天才黑客 题目链接 T2 BZOJ.4913.[SDOI2017]遗忘的集合 题目链接 正解生成函数什么的 部分分有点坑 弃了 T3 BZOJ.4914.[SDOI2017]文本校正 题目链接 考试代码 T1 #include <cstdio> #include <cctype> #include <c

TYVJ NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第二轮Day2题解

肝了两题... T1一眼题,分解质因数,找出2的个数和5的个数取min输出 #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=1000010,inf=1e9; int n,m,T; int fac2[m

tyvj NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day2题解

上星期打的...题有点水,好多人都AK了 T1排个序贪心就好了 #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=500010,inf=1e9; struct poi{int e,s;}a[maxn];

1856: [Scoi2010]字符串

1856: [Scoi2010]字符串 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 847  Solved: 434[Submit][Status] Description lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数.现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗? Input 输入数据是一行,包

1296: [SCOI2009]粉刷匠

1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 916  Solved: 532[Submit][Status] Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被粉刷一次. 如果windy只能粉刷 T 次,他最多能正确粉刷多少格子? 一个格子如果