1113

1.抓球
【问题描述】
何老板有N个不透明的箱子,编号1到N。每个箱子里都有若干大小相同的
小球,每个小球上都有一个编号。其中i号箱子里的小球编号是Xi到Yi,也就
是编号Xi,Xi+1,Xi+2,...,Yi-1,Yi的小球都在i号箱子里。
你需要从每个箱子里随机抓一个球出来, 从i号箱子抓出任意一个球的概
率都是1/(Yi-Xi+1)。如果你抓出的N个球中,有大于等于S%的球的编号第一
位都是1(比如: 15, 138, 1196的第一位都是1),那么你将赢得一次与何老
板共进午餐的机会。
问,你赢得美妙午餐的概率有多大?

解:
由于没开LL 掉40....
DP一下即可
code:

//
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define GC getchar()
#define D double
#define maxnn 2100
ll sum[maxnn];
ll n,s;
D f[maxnn][maxnn];
ll res[maxnn];
ll xx[maxnn],yy[maxnn];
double ans=0;
inline ll R() {
	char t;
	int f=1;
	ll x=0;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}

int main() {
	sum[1]=1;
	for(int i=2; i<=20; i++) {
		sum[i]=sum[i-1]*10;
	}
	for(int i=2; i<=20; i++) {
		sum[i]=sum[i-1]+sum[i];
	}
	n=R();
	s=R();
	ll x,y;
	for(int i=1; i<=n; i++) {
		x=R();
		xx[i]=x;
		y=R();
		yy[i]=y;
		x--;
		string s1,s2;
		while(x) {
			s1.push_back((x%10)+48);
			x/=10;
		}
		ll tmp1=0;
		if(s1.back()!='1') {
			tmp1+=sum[s1.size()];
		} else {
			ll remake1=0;
			for(int k=s1.size()-2; k>=0; k--) {
				remake1=(remake1*10+s1[k]-'0');
			}
			tmp1+=sum[s1.size()-1]+remake1+1;
		}
		while(y) {
			s2.push_back((y%10)+48);
			y/=10;
		}
		ll tmp2=0;
		if(s2.back()!='1') {
			tmp2+=sum[s2.size()];
		} else {
			ll remake2=0;
			for(int k=s2.size()-2; k>=0; k--) {
				remake2=(remake2*10+s2[k]-'0');
			}
			tmp2+=sum[s2.size()-1]+remake2+1;
		}
		res[i]=tmp2-tmp1;
	}
	f[0][0]=1.0;
	for(int i=1; i<=n; i++) {
		for(int j=0; j<=i; j++) {
			if(j==0) {
				f[i][j]=f[i-1][j]*((yy[i]-xx[i]+1-res[i])/1.0/(yy[i]-xx[i]+1));
			} else {
				f[i][j]=f[i-1][j-1]*(res[i]/1.0/(yy[i]-xx[i]+1))+f[i-1][j]*(((yy[i]-xx[i]+1)-res[i])/1.0/(yy[i]-xx[i]+1));
			}
		}
	}
	for(int i=(ceil(n*(s/1.0/100))); i<=n; i++) {
		ans+=f[n][i];
	}
	printf("%.7lf",ans);
}

B
【问题描述】
游戏LOL中的召唤师峡谷地图是一个有n个节点, m条单向道路构成的。最
近,游戏推出了一个新英雄,他拥有特殊技能,对于峡谷中的任意一个节点
x,可以把所有以x为终点的边的权值减少d,同时把所有以x为起点的边的权值
加上d。 现在我们操控新英雄使用他的技能,让所有边的权值的最小值最大。
边的权值>0。
解:
二分+差分约束
看到infinite 我想多了
超过就是infinite...
二分答案跑负环即可
code;

/
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define maxnn 6000
#define inf 1000000000
int dis[maxnn];
int n ,m;
int las[maxnn],en[maxnn],nex[maxnn],tot,le[maxnn];
void add(int a,int b,int c) {
	en[++tot]=b;
	nex[tot]=las[a];
	las[a]=tot;
	le[tot]=c;
}
int mapp1[maxnn][maxnn];
#define GC getchar()
inline int R() {
	char t;
	int f=1;
	int x=0;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}
int cnt[maxnn];
int mark[maxnn];
int fla=1;
bool spfa(int x,int mid)
{
    for(int i=las[x];i;i=nex[i])
    {
        int v=en[i];
        if(dis[v]>dis[x]+le[i]-mid)
        {
            dis[v]=dis[x]+le[i]-mid;
            if(mark[v])return false;
            mark[v]=1;
            if(!spfa(v,mid))return false;
        }
    }
    mark[x]=0;
    return true;
}
  

bool isok(int mid) {
	for(int i=0;i<=n;i++)
	{
		mark[i]=0;	
		dis[i]=inf;
	}
	dis[0]=0;
	mark[0]=1;
	if(!spfa(0,mid))
	 return false;
	return true;
}
int main() {
	while(cin>>n>>m) {
		int a,b,c;
		memset(las,0,sizeof(las));
		tot=0;
		for(int i=1; i<=m; i++) {
			a=R();
			b=R();
			c=R();
			add(a,b,c);
		}
		for(int i=1; i<=n; i++) {
			add(0,i,0);
		}
		int l=0,r=110100;
		while(l<=r) {
			int mid=(l+r)>>1;
			if(isok(mid)) {
				l=mid+1;
			} else {
				r=mid-1;
			}
		}
		if(l>10000) {
			{
				printf("Infinite\n");
				continue;
			}
		}
		if(l==0) {
			printf("No Solution\n");
			continue;
		}
		printf("%d\n",r);
		continue;
	}
	return 0;
}

C 攻略
时间限制 : - MS 空间限制 : - KB
评测说明 : 1s,128m
问题描述
题目简述:树版[k取方格数]
众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。今天他得到了一款新游戏《XX半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状
结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的) “为什么你还没玩就知道每个场景的价值呢?”
“我已经看到结局了。”
解:
长链剖分
考试的时候我居然以为这个东西有后效性..... 然而没有...
或者树形DP记录是哪个儿子传给的 扔进堆里面就行了每次找的时候 更新就行了 ...
或者线段树+dfs序列
记录树上前缀和
每次查找的时候找最长的
然后往上减 去掉子树的影响就行了
code:

//
#include<bits/stdc++.h>
using namespace std;
#define maxnn 400010
#define ll long long 
ll las[maxnn],en[maxnn],nex[maxnn],tot;
ll a[maxnn];
ll n,m;
struct node {
	ll st,en,l;
};
bool operator <(node a,node b) {
	return a.l<b.l;
}
priority_queue<node> Q;
ll ff[maxnn];
#define GC getchar()
inline ll R() {
	char t;
	int f=1;
	ll x=0;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}
void add(int a,int b) {
	en[++tot]=b;
	nex[tot]=las[a];
	las[a]=tot;
}
ll f[maxnn],id[maxnn];
void DP(int v,int fa) {
	ff[v]=fa;
	for(int i=las[v]; i; i=nex[i]) {
		int u=en[i];
		if(u==fa) continue;
		DP(u,v);
		if(f[u]>f[v]) {
			f[v]=f[u];
			id[v]=id[u];
		}
	}
	if(id[v]==0) {
		id[v]=v;
	}
	f[v]+=a[v];
}
int main() {

	n=R();
	m=R();
	for(int i=1; i<=n; i++) {
		a[i]=R();
	}
	int x,y;
	for(int i=1; i<n; i++) {
		x=R();
		y=R();
		add(x,y);
		add(y,x);
	}
	DP(1,1);
	for(int i=las[1]; i; i=nex[i]) {
		int u=en[i];
		Q.push(node {u,id[u],f[u]});
	}
	ll ans=0;
	while(m--) {
		ans+=Q.top().l;
		node r=Q.top();
		int d=r.en;
		int pos;
		pos=d;
		while(d!=ff[r.st]) {
			for(int i=las[d]; i; i=nex[i]) {
				int u=en[i];
				if(u==pos) continue;
				if(u==ff[d]) continue;
				Q.push(node{u,id[u],f[u]});
			}
			pos=d;
			d=ff[d];
		}
		Q.pop();
	}
	cout<<ans+a[1];
}

长链剖分:
贪心地选取代价最大的链

//
#include<bits/stdc++.h>
using namespace std;
#define maxnn 400010
#define ll long long
ll las[maxnn],en[maxnn],nex[maxnn],tot;
ll a[maxnn];
ll n,m;
priority_queue<ll> Q;
ll ff[maxnn];
#define GC getchar()
inline ll R() {
	char t;
	int f=1;
	ll x=0;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}
void add(int a,int b) {
	en[++tot]=b;
	nex[tot]=las[a];
	las[a]=tot;
}
ll f[maxnn],id[maxnn];
ll son[maxnn];
int topp[maxnn];

void dfs1(int v,int fa) {
	for(int i=las[v]; i; i=nex[i]) {
		int u=en[i];
		if(u!=fa) {
			dfs1(u,v);
			if(f[u]>f[v]) {
				f[v]=f[u];
				son[v]=u;
			}

		}

	}
	f[v]+=a[v];
}
void dfs2(int v,int fa,int t) {
	topp[v]=t;
	if(son[v]) {
		dfs2(son[v],v,t);
	}
	for(int i=las[v]; i; i=nex[i]) {
		int u=en[i];
		if(u==son[v]) continue;
		if(u!=fa) {
			dfs2(u,v,u);
		}
	}
}
int main() {
	
	n=R();
	m=R();
	for(int i=1; i<=n; i++) {
		a[i]=R();
	}
	int x,y;
	for(int i=1; i<n; i++) {
		x=R();
		y=R();
		add(x,y);
		add(y,x);
	}
	dfs1(1,1);
	ll ans=0;
	dfs2(1,1,1);
	for(int i=1; i<=n; i++) {
		if(topp[i]==i) {
			Q.push(f[i]);
		}
	}
	while(m--) {
		ans+=Q.top();
		Q.pop();
	}
	cout<<ans;
}
posted @ 2019-11-13 15:24  ALEZ  阅读(567)  评论(0编辑  收藏  举报