SDKD 2021 Summer Training Series B 2nd Round

A - Appeal to the Audience
题意:
判断:树,节点,父节点emmmm签到签到
B - Breaking Branches
题意:给定一长度为n的线段,Alice和Bob轮流切割线段使之成为两个整数段,最后进行切割的人获胜。若Alice 胜,输出“Alice”,和第一步操作数;否则输出“ Bob”。
所以就是切到最后两端都为1,看谁切最后一刀
判断:n的长度要切n-1刀

#include<iostream>
#include<cstring>
using namespace std;
int main(){
    int n;
    cin>>n;
    if(n%2==0)
        cout<<"Alice"<<endl<<n-1<<endl;
    else
        cout<<"Bob"<<endl;
}

C
D
E - Efficient Exchange
题意:只有整型钞票,都是十的倍数,还有一,然后有好几种方法交易,问怎么样交易的纸币数量最少,一也是纸币
判断:我先想的正着走,结果进位什么的进的我头大,然后反正是最值问题,就想到用动规,对于每一位数字来说前一位数字都会影响这一位数字的值,所以就能构成状态,状态又分进位和不进位以及他上一位数进位还是不进位,然后动规
应该是最短代码了

#include<iostream>
#include<cstring>
using namespace std;
int dp[10000][10000];
int main(){
    string str;
    int n;
    cin>>str;
    n=str.length();
    dp[0][0]=0;
    dp[0][1]=1;
    for(int i=0;i<n;i++){
        dp[i+1][0]=min(dp[i][0]+str[i]-'0',dp[i][1]+10-str[i]+'0');
        dp[i+1][1]=min(dp[i][0]+str[i]-'0'+1,dp[i][1]+9-str[i]+'0');
    }
    cout<<dp[n][0]<<endl;
}

F - Find my Family
题意:Alice比我高在我左边Bob比我俩都高在我右边,给你一堆照片,问符合条件的一共有几张,并输出是第几张照片符合条件
判断:据(●—●)的笔记分析
维护单调上升序列,每次加入元素前的删除元素记录所删除的最后一个值,每次删之前拿新元素和这个值比较,如果新元素大则这组数据合法。摘自(●—●)笔记
有歧义啊,应该是中间隔着人没关系,也算是符合,代码是解决这个问题的

#include <bits/stdc++.h>
using namespace std;
int k,n,h[300005],pos,que[300005],ac[1005],num,tmp;//que来暂存可能的Alice和我
int main()
{
    cin>>k;
    for(int i=1;i<=k;i++)
    {
        scanf("%d",&n);
        bool ans=0;
        pos=0;
        tmp=(1e9)+1;//暂存比较数列

        for(int j=1;j<=n;j++)
        {
            scanf("%d",&h[j]);
            while(pos&&que[pos]>=h[j])//上一个数大
            tmp=que[pos--];//暂存前前数
            if(h[j]>tmp) ans=1;//刚输入的这个比他前前面都大,ans就是true
            que[++pos] = h[j];//相当于pos一直维持在1-3
        }
        if(ans)//这张照片符合条件
            ac[++num]=i;
    }
    cout<<num<<endl;
    for(int i=1;i<=num;i++)
        cout<<ac[i]<<endl;
    return 0;
}

G - Gluttonous Goop
题意:有个菌种会感染周围八个宫格,
判断:当时我看到以为是bfs,结果网上题解都说是线段树那只能待补题了
H - Historic Exhibition
题意:给花瓶,给展台然后匹配问题
判断:刚开始猛上去就是二分匹配法,结果匈牙利算法太大了,需要简化,看(●—●)的题解是要用网络流,然而这是我目前无法get的领域
I
J - Jazz it Up!
题意:输入n,2<=m<n,2<=k&&kk<mn,求符合条件的任意一个m即可
判断:水题,就是题意比较难看懂

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n,flag;
    cin>>n;
    for(int m=2;m<n;m++)
    {
        flag=0;
        for(int k=2;k*k<n*m;k++)
        {        
            if((m*n)%(k*k)==0)
                flag=1;
        }
        if(flag==0)
        {
            cout<<m;
            return 0;
        }
    }
}

K
L - Lucky Draw
题意:2<=n<=50个人, 1≤k≤50条命,0.1≤p≤0.9 点存活概率,有n个人玩游戏,每个人拥有k条生命。每轮每个人会有p的概率不会死,求最后是平局的概率
判断:看了网上的题解,万万没想到会是一道动规,这藏得比E还深啊,压根没往动规想,灵感还是很重要的
搬运判断:设f[i][j]表示i轮后剩余j条生命的概率,那么 f[i][j] = p * f[i - 1][j] + (1 - p) * f[i - 1][j + 1]
由于生命都相同,P(平局) = 1 - P(某人赢) = 1 - n* P(第一个人赢) = 1 - n * sum( P(第一个人第i轮赢其余人i-1轮死) )
————————————————
版权声明:本文为CSDN博主「moomhxy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41785863/article/details/105069753

#include<bits/stdc++.h>
using namespace std;
double f[1005][1005];
int main(){
    int n,m;
    double p;
    cin>>n>>m>>p;
    f[0][m]=1;//第0轮后剩余m条生命的概率是1
    for(int i=1;i<1005;++i)//等下试一下++i和i++的区别
    {//这些是针对一个人的
        for(int j=m;j>0;j--)
            f[i][j]=p*f[i-1][j]+(1-p)*f[i-1][j+1];//第i轮过后还有j条命的概率=前一轮保命的概率+前一轮丢命的概率
      f[i][0]=f[i-1][0]+(1-p)*f[i-1][1];//生命耗尽时不用乘以概率,前一次如果是保命继承的话,必定是百分之百概率
    }
    double ans=0;//平局的概率
    for(int i=1;i<1005;++i)//一千次以后的概率对答案的影响很小
    {
        ans+=(f[i][0]-f[i-1][0])*pow(f[i-1][0],n-1);//计算在i轮死亡并且其他人都在i轮之前死亡的概率
    }
    printf("%.10f\n", 1 - n * ans);//对每个人都要满足计算在i轮死亡并且其他人都在i轮之前死亡的概率
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值