bupt暑假排位赛(2)

    这次训练的题目,两道水题(卡数据类型,有好多人不能1A,我也在内),还有3道题,不是很容易。

 A. BOJ0416丁神去谷歌

          一道很水的题,因为我刚开始用了sort,T了一次,后来又忘了是什么原因RE了2次尴尬,最后,就直接读入的时候比较的,很水,想多了。

         下面简单分析一下吧,由于是要求b/a的最大值,所以只需要把当前的b/a与之前最大的b/a比较就行,如果相同的话(在这了需要主语,如果你用的是交叉相乘来比较,记得用long long,如果你用的是b/a来比较,在判断是否相等的时候记得浮点型的精度问题,可以用abs(max-(double)b/a)<=1e-9 之类的式子来判断,不要直接用等号),再去比较a的大小,由于本身序号就是从小到大的,所以也不用担心这个了(只要a相等的时候别更新答案就行),说的有点多了,附代码吧

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
 
#define N 100005
 
using namespace std;
 
int main()
{
    int t;
    double MAX=0;
    cin>>t;
    while (t--)
    {
        int n;
        int ans,ansa;
        MAX=0;
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            double c=(double)b/a;
            if (MAX<c)
            {
                MAX=c;
                ans=i;
                ansa=a;
            }
            else if(abs(MAX-c)<=1e-10)
            {
                if (a<ansa)
                {
                    ans=i;
                    ansa=a;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">B题,</span><a target=_blank href="http://code.bupt.edu.cn/problem/p/417/" target="_blank" style="font-family: Arial, Helvetica, sans-serif;">boj0417丁神又去谷歌</a>

  赤果果的一道0-1背包,记得要用long long 就行,直接附代码

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
 
#define N 1005
 
using namespace std;
 
long long dp[N];
 
int a[N],b[N];
 
int main()
{
    int T;
    cin>>T;
    while (T--)
    {
        int n,t;
        scanf("%d%d",&t,&n);
        memset(dp,0,sizeof(dp));
        for (int i=1;i<=n;i++)
            scanf("%d%d",&a[i],&b[i]);
 
        for (int i=1;i<=n;i++)
            for (int j=t;j>=a[i];j--)
                dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
        printf("%lld\n",dp[t]);
    }
    return 0;
}


 C. boj426 goblin

   这个题呀,昨天比赛时有思路(PS:今天想了一上午,发现我的思路是在是太难实现了),最终还是选择了lyz大神的思路。

   题意大概是求n以内(1--n)的数的全排列中,符合交叉排列的情况(即<><><><><>,大于号小于号交叉出现的情况)总共有多少种,结果对p取余。

   我就来说说lyz大神的思路吧,用到了排列组合的思想。

    首先,为了方便叙述,我先来给交叉排列的两种情况命一下名,

           假设:第一个数大于第二个数的情况叫做D情况,第一个数小于第二个数的情况叫做P情况,对于k个数的排列,我们记D情况共有D[k]种,P情况共有P[k]种,(记              P[0]=P[1]=P[2]=1     那么,就有D[k]=P[k](至于怎么来证明,其实很简单,我们来看两个图

    

所有D情况都可以抽象成左图图(W型),所有的P情况都可以抽象成右图(M型),

对于D情况,可以抽出n个数中的最大数,分别放到各个凸起点(途中红圈标出),经过一些排列组合的运算,可以得到一个一个结果。

同理,对于P情况,可以抽出n个数中的最小数,分别放到各个凹陷点(图中红圈标出),根据对称的特性,就可以得到跟D情况相同的结果。

所以,我们只需考虑一种情况了,我选取的D情况,经过排列组合的运算,很容易得到如下的关系(sigma代表求和符号

D[k]=sigma(D[i[*D[k-1-i]*C[k-1][k-1-i]) (可能看这个式子看不懂,自己推导一下吧,分别把最大的数放到凸起点就可以了,很容易的)

好了,下面附代码(PS:被memset坑了好久,也学到了一点,在程序中,你如果开了数组但是没有用到,提交时内存是不算的,如果你用了memset(a,0,sizeof(a))来初始化数组,那么这个数组就算是全部被使用了。这题中,如果用memset来初始化组合数的存储数组,就会超出内存限制。算是学到了一点吧!还有就是,如果用动态数组来做的话,是擦边过得,我是第一次交1000ms, T了,第二次993ms过了。最后,注意D数组要用long long,即便不用,运算时也记得转化一下,否则会WA的)。

#include <iostream>
#include <cstdio>
#include <cstring>
  
#define N 4205
int C[N][N]={0};
long long g[N]={0};
int n,p;
  
void init()
{
    memset(g,0,sizeof(g));
    g[3]=2;
    g[2]=1;
    g[1]=1;
    g[0]=1;
  
    for (int i=1;i<=n;i++)
    {
        C[i][0]=C[i][i]=1;
        for (int j=1;j<i;j++)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;
  
    }
  
    for (int i=4;i<=n;i++)
        for (int j=0;j<=i-1;j+=2)
            g[i]=(g[i]+(g[j]*g[i-1-j]%p)*C[i-1][i-1-j])%p;
  
}
  
int main()
{
    while (~scanf("%d%d",&n,&p))
    {
        init();
        printf("%d\n",2*g[n]%p);//输出不用lld是因为取余以后就在int的范围内了。
    }
}
    D题,boj0427 学姐逗学弟

    一道博弈题目,比赛时看错题了。。。今天下午基本上全花在这个题上了,根源还是memset尴尬,通过个题我了解到:用memset来初始化数组也是要花O(n)的时间的,它比直接赋值快大约4倍,但是计算复杂度时还是要按照O(n)的复杂度考虑进去的。在此感谢zsp同学帮我找到这个错误。

     好了,进入正题。这是一个博弈问题,Every-Sg游戏,直接说思路吧,题目可以自己点开链接来看。

     首先,我们定义每个节点的高度为所有人都采取最优策略,一直到游戏结束所需要走的步数。思路很简单,对于必败点,走这一步的人必输,那么他肯定想尽快结束这一个游戏,所以他会选择它的所有子节点中高度最小的来走;对于必胜点,走这一步的人,想要胜利,就必须走到必败点上去,而他又想把游戏时间尽量拉长,所以他肯定会选择所有必败子节点中高度最大的那个节点来走。这样分析的话,就很容易递归的定义出一个点的高度了。然后再根据给的石子的位置来判断,比较高度最大的必胜点和高度最大的必败点的大小,就可以判断是不是学姐赢了。

   这个代码是有注释了(为了让zsp同学帮忙找下错误而标注的,再次进行感谢),贴代码

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#define N 100005
 
using namespace std;
#define INF 10000000
vector <int> tree[N];
 
bool judgeSg[N]={false};//判断子节点出现的sg值
int father[N]={0};//记录某个节电的父亲节点
int depth[N]={0};//记录“高度”(懒得改了)
int sg[N]={0};//对于单个游戏来说的每个节点的sg值。
int n,m;
 
void init()//初始化
{
    memset(father,0,sizeof(father));
    memset(depth,0,sizeof(depth));
    memset(sg,0,sizeof(sg));
    for (int i=1;i<=n;i++)
        tree[i].clear();
}
 
void solveSg(int now)//now代表当前节点,dfs
{
    int MAX=0,MIN=INF;
 
    if (tree[now].size()==0)
    {
        sg[now]=0;
        depth[now]=0;
        return ;
    }//搜到叶子节点,叶子节点对应的高度为0,sg值为0;
    for (int i=0;i<tree[now].size();i++)
    {
        int son=tree[now][i];
        solveSg(son);//dfs
 
        if (MIN>depth[son])
            MIN=depth[son];//记录所有子节点中的最小高度(如果当前节点是必败节点的话用得到)
        if (sg[son]==0)//子节点为必败态
            if (MAX<depth[son])
                MAX=depth[son];//记录所有必败子节点中的最大高度(如果当前节点是必胜节点用得到)
    }
    memset(judgeSg,false,sizeof(tree[now].size()+10));//初始化sg判断数组
     for (int i=0;i<tree[now].size();i++)
    {
        int son=tree[now][i];
        judgeSg[sg[son]]=true;//记录出现的sg值
    }
    int res=0;
 
    while (judgeSg[res]) res++;
 
    if (res==0)//此点为必败态
        depth[now]=MIN+1;
    else //为必胜态
        depth[now]=MAX+1;
 
    sg[now]=res;//当前节点的sg值
}
int main()
{
    int T;
    cin>>T;
    while (T--)
    {
        int maxWin=0,maxFail=0;//分别记录必胜点和必败点的最大高度
 
        scanf("%d%d",&n,&m);
        init();
        for (int i=2;i<=n;i++)
        {
            scanf("%d",&father[i]);
            tree[father[i]].push_back(i);
        }//动态数组建树(单向的)
        solveSg(1);//dfs
        for (int i=1;i<=m;i++)
        {
            int stone;
            scanf("%d",&stone);
            if (sg[stone]==0)
                maxFail=max(maxFail,depth[stone]);
            else
                maxWin=max(maxWin,depth[stone]);
        }
        if (maxWin>maxFail)//必胜的游戏时间长,学姐赢
            printf("MengMengDa!\n");
        else
            printf("So sad...\n");
    }
    return 0;
}
 
   E题,好吧,我承认,还没做,先放放吧!

  

         

    

bupt linux上机作业2 是一项关于Linux操作系统的实践作业,要求对Linux系统进行操作和管理。以下是针对该作业的回答: bupt linux上机作业2 主要涉及以下几个方面的内容: 1. 基本命令的使用:在Linux系统中,我们可以使用一些基本的命令来进行文件和目录的操作,如ls、cd、mkdir、rm等。这些命令的使用是我们平时操作Linux系统的基础,要求掌握它们的基本用法。 2. 文件权限的设置:在Linux系统中,每个文件和目录都有自己的权限,包括读、写、执行等。在这个作业中,我们需要学会如何使用chmod命令来设置文件和目录的权限,以保护系统的安全性。 3. 进程管理和任务调度:Linux系统中的进程管理和任务调度是非常重要的内容。在这个作业中,可以通过使用ps、kill等命令来查看和管理系统中的进程,以及使用cron命令来设置定时任务。 4. 软件包的安装和管理:Linux系统中有很多开源软件包可以供我们使用。在这个作业中,可以学习如何使用apt-get或yum等包管理器来安装和管理软件包,以满足系统中各种软件的需求。 通过完成bupt linux上机作业2,我们可以加深对Linux操作系统的理解和掌握,提升对Linux系统的管理能力。这对于计算机相关专业的学生来说是非常有益的,也是日后工作中可能会用到的技能。希望以上回答能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值