D:概率论
条件概率:求在某个条件发生的概率下,另一个条件发生的概率.
公式P(A|B) = P(AB)/P(A).
在这题中即可看成 恰好有k枚的概率/至少m枚的概率.
对于至少m枚的概率.
容斥求最多m-1枚反面的概率.
0枚反面时 C(n,0) * (1/2)^n
1枚反面时 C(n,1) * (1/2)^2
....
1减去这个和即为至少m枚反面的概率.
恰好k枚正面的概率C(n,k)*(1/2)^n.
Code:
LL f[N];
void init()
{
f[0] = 1;for(int i=1;i<N;++i) f[i] = (f[i-1]*i)%Mod;
}
LL quick_mi(LL a,LL b)
{
LL re = 1;
while(b)
{
if(b&1) re = (re*a)%Mod;
a = (a*a)%Mod;
b >>= 1;
}
return re;
}
LL inv(LL n){return quick_mi(n,Mod-2)%Mod;}
LL C(LL n,LL m)
{
return f[n]*inv(f[m])%Mod*inv(f[n-m])%Mod;
}
int main()
{
init();
int t;sd(t);
while(t--)
{
int n,m,k;sddd(n,m,k);
if(m+k > n) printf("0\n");
else
{
LL ma1 = C(n,k)*inv(quick_mi(2,n))%Mod;
LL tmp = 0;
for(int i=0;i<m;++i)
{
tmp = (tmp+C(n,i)*inv(quick_mi(2,n))%Mod)%Mod;
}
tmp = (1-tmp+Mod)%Mod;
LL ans = ma1*inv(tmp)%Mod;
plr(ans);
}
}
system("pause");
return 0;
}A:树形dp.(注意不包括路径上的点的权值)
dp[i]表示i点向下的最大价值。
对面每个点有两种情况
1.以这个点为中间媒介,这个点的两条子节点上的边相连为最大.
2.以这个点为起点,和向下的某条子节点边上的点相连为最大.
所以边更新dp值边进行比较,同时最后比较自己为起点,那么dp[i]显然就是i点往下的最大价值了,注意的是,这个dp[i]在最后更新完时显然已经将和子节点的边的权值计算在内。
然后dp[i]也可能是a[i],所以最后还要更新一下。
Code:
struct Node{int to,dis;};
LL a[N],dp[N],ans;
vector<Node> G[N];
void dfs(int u,int fa)
{
for(auto t:G[u])
{
int v = t.to,d = t.dis;
if(v == fa) continue;
dfs(v,u);
ans = max(ans,dp[u]+dp[v]+d);//以u为中间媒介,通过之前更新的最大dp[u]来更新dp[v].
dp[u] = max(dp[u],dp[v]+d);//以v或者v以下的点为终点;显然dp[v]已经与a[v]比较过;
}
ans = max(ans,dp[u]+a[u]);//以u为起点
dp[u] = max(dp[u],a[u]);
}
int main()
{
int t;sd(t);
while(t--)
{
ans = -INF;
int n;sd(n);
for(int i=1;i<=n;++i) G[i].clear(),dp[i] = -INF;
for(int i=2;i<=n;++i)
{
int x,y;sdd(x,y);
G[i].push_back(Node{x,y});
G[x].push_back(Node{i,y});
}
for(int i=1;i<=n;++i) sld(a[i]);
dfs(1,0);
plr(ans);
}
// system("pause");
return 0;
}
京公网安备 11010502036488号