• 2020牛客寒假算法基础集训营5


    题目链接:https://ac.nowcoder.com/acm/contest/3006#question

    每场都非常的稳。。。稳的辣鸡

    题目说明:

    A.模板                         B.牛牛战队的比赛地      C.C语言IDE      D.牛牛与牛妹的约会

    (贪心)                    (三分)                        (大模拟)         (贪心)

    E.Enjoy the game       F.碎碎念                        G.街机争霸        H.Hash

    (找规律)                 (DP)                          (BFS)           (字符串水题)

    I.I题是个签到题          J.牛牛战队的秀场

    (水题)                   (思维)

    A.模板

    题目大意:两个字符串互变,问至少要多少步,变化规则:

    • 将其中任意一个字母替换为另一个
    • 把最后一个字母删除
    • 在尾部添加一个字母

    示例

    输入

    4 3
    WXYZ
    WXY

    输出

    1

    没什么好说的,先把长度变成一样长,那么就需要$len(a)-len(b)$步,接下来就是将所有不一样字母的个数加起来就好了

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int mac=1e5+10;
    
    char s1[mac],s2[mac];
    
    int main(int argc, char const *argv[])
    {
        int n,m;
        scanf ("%d%d",&n,&m);
        scanf ("%s%s",s1,s2);
        int ans=max(n,m)-min(n,m);
        for (int i=0; i<min(n,m); i++){
            if (s1[i]!=s2[i]) ans++;
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    B.牛牛战队的比赛地、

    题目大意:在x轴上找一点,使得其距离n个点的最大距离最小

    示例

    输入

    3
    0 0
    2 0
    0 2

    输出

    2

    。。。。没注意看题,然后写了个三分套三分,然后发现输出是个$sqrt{2}$。。。。然后就发现固定在了x轴,那么我们直接三分x轴就好了。不过为了增加精度,我们最后再开方。

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    const int mac=1e5+10;
    const int inf=1e9+10;
     
    struct node
    {
        int x,y;
    }pt[mac];
    int n;
    double sans=inf;
     
    double dis(double x)
    {
        double ans=0;
        for (int i=1; i<=n; i++){
            double dist=(x-pt[i].x)*(x-pt[i].x)+(pt[i].y)*(pt[i].y);
            ans=max(ans,dist);
        }
        sans=min(sans,ans);
        return ans;
    }
     
    int main(int argc, char const *argv[])
    {
        scanf ("%d",&n);
        int xma=-inf,xmi=inf,yma=-inf,ymi=inf;
        for (int i=1; i<=n; i++){
            int x,y;
            scanf ("%d%d",&x,&y);
            pt[i]=node{x,y};
            xma=max(x,xma);xmi=min(x,xmi);
            yma=max(y,yma);ymi=min(y,ymi);
        }
        double lx=xmi,rx=xma,ly=ymi,ry=yma;
        for (int i=1; i<=50; i++){
            double mid1=(lx+rx)/2;
            double mid2=(mid1+rx)/2;
            ly=ymi,ry=yma;
            if (dis(mid1)<dis(mid2)) rx=mid2;
            else lx=mid1;
        }
        printf("%.5f
    ",sqrt(sans));
        return 0;
    }
    View Code

    C.C语言IDE

    题目大意:

    示例

    输入

    #include <stdio.h>
    
    int plus(int a, int b)
    {
    	return a + b;
    }
    int main()
    {
    	int a,b;
    	scanf("%d%d", &a, &b);
    	printf("%d
    ", plus(a, b)); 
    	return 0;
    }
    

    输出

    int plus(int,int)
    int main()

    D.牛牛与牛妹的约会

    题目大意:T组数据(5e5)给你$a,b$两点,你要从$a$到$b$,你可以花费1距离/1单位时间,也可以花费1单位时间从$x$位置到$sqrt[3]{x}$,问你a到b的最少时间。

    示例

    输入

    2
    3 -1
    1 2

    输出

    3.442249570
    1.000000000

    每次走的时候比较直接走和闪现那个更优就行了,如果直接走比闪现更优,说明之后都是直接走更优了,我们break,注意一下pow函数需要对负数特殊处理

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
        int t;
        scanf ("%d",&t);
        while (t--){
            int a,b;
            scanf ("%d%d",&a,&b);
            double x=a,y=b,nx;
            double ans=0;
            while(1){
                if (x<0) nx=-pow(-x,1.0/3.0);
                else nx=pow(x,1.0/3.0);
                if (fabs(nx-y)<fabs(x-y)-1) ans+=1,x=nx;//比较两个谁更优
                else {ans+=fabs(x-y); break;}
            }
            printf("%.8f
    ",ans);
        }
        return 0;
    }
    View Code

    E.Enjoy the game

    题目大意:Bob和Alice博弈,规则如下:

      • 初始一共有n张卡牌
      • 先手第一步最少要拿1张牌,最多要拿n-1张牌。
      • 接下来每一步,双方最少要拿1张牌,最多拿等同于上一步对方拿的牌数的牌。
      • 拿走最后一张牌的人将取得游戏的胜利。

    示例

    输入

    2

    输出

    Alice

    这题,找规律。。。没什么好说的,大胆尝试,交他一发,然后证明了$2^{k}$则Alice获胜,否则就是Bob

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
        long long n;
        cin>>n;
        int mark=0;
        while (n>1){
            if (n&1) mark=1;
            n>>=1;
        }
        if (mark) cout<<"Bob"<<endl;
        else cout<<"Alice"<<endl;
        return 0;
    }
    View Code

    F.碎碎念

    题目大意:AC一道题会说一句话,RJ一道题会说$x$句话,问,如果他说了$[l,r]$句话,那么他有几种有效提交序列

    示例

    输入

    3
    3
    3 3
    1 4
    1 5

    输出

    2
    7
    11

    一眼DP。。。我们的第$i$句话肯定是由第$i-1$和第$i-x$句或转移过去的那么我们只需要想想怎么转移过去了,我们设$dp[i][0/1]$($dp[i][0]$表示$i-1$句话AC到i),然后$i-x$只能AC状态转移过去即:

    $dp[i][0]=dp[i-1][0]+dp[i-1][1]$

    $dp[i][1]=dp[i-x][0]$

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    const ll mod=1e9+7;
    const int mac=1e5+10;
    
    ll dp[mac][5];
    
    int main(int argc, char const *argv[])
    {
        int x,q;
        scanf ("%d%d",&x,&q);
        dp[0][0]=1;
        for (int i=1; i<mac; i++){
            if (i<x)
                dp[i][0]=(dp[i-1][0]+dp[i-1][1])%mod;
            else {
                dp[i][0]=(dp[i-1][0]+dp[i-1][1])%mod;
                dp[i][1]=(dp[i-x][0])%mod;
            }
            dp[i][2]=(dp[i][0]+dp[i][1])%mod;
            dp[i][2]=(dp[i][2]+dp[i-1][2])%mod;
        }
        while (q--){
            int l,r;
            scanf ("%d%d",&l,&r);
            ll ans=dp[r][2]-dp[l-1][2];
            ans=(ans+mod)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    G.街机争霸

    题目大意:

    示例

    输入

    3 3 1 3
    &&A
    ###
    &&L
    2 1 RIGHT

    输出

    2

    H.Hash

    题目大意:给你一个长度为6的字符串和hash值的mod,让你构造一个一样长的字符串,字典序大于原来的,使得其hash值与原来的一样

    示例

    输入

    abcdef 11

    输出

    abcdeq

    。。。实际上就是个26进制的的加法,我们在原来的Hash值上直接加上mod就好了,然后就开始进位就好了

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int LEN = 6;
    
    char s[10];
    int mod,p[10];
    
    void solve()
    {
        for(int i=0; i<6; i++)
            printf("%c",p[i]+'a');
        printf("
    ");
    }
    
    int main(int argc, char const *argv[])
    {
        while (~scanf ("%s%d",s,&mod)){
            for (int i=0; i<6; i++)
                p[i]=s[i]-'a';
            p[5]+=mod;
            if (p[5]<26) {solve(); continue;}
    
            p[4]+=p[5]/26;
            p[5]%=26;
            if (p[4]<26) {solve(); continue;}
    
            p[3]+=p[4]/26;
            p[4]%=26;
            if (p[3]<26) {solve(); continue;}
    
            p[2]+=p[3]/26;
            p[3]%=26;
            if (p[2]<26) {solve(); continue;}
    
            p[1]+=p[2]/26;
            p[2]%=26;
            if (p[1]<26) {solve(); continue;}
    
            p[0]+=p[1]/26;
            p[1]%=26;
            if (p[0]<26) {solve(); continue;}
    
            printf("-1
    ");
        }
        return 0;
    }
    View Code

    I.I题是个签到题

    题目大意:给你n,m(题目数量,总人数)和n道题的过题人数,然后让你判断I题是否是签到题(有80%的人过了或者过题人数前3名的)

    示例

    输入

    9 100
    100 100 100 100 100 100 100 100 100

    输出

    Yes

    这题确实是个签到题。。。不过需要注意的是人数会有小数点所以要特判一下。。。我就是这里被卡了10来min。。。。

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
     
    int a[20];
     
    bool cmp(int x,int y)
    {
        return x>y;
    }
     
    int main(int argc, char const *argv[])
    {
        int n,m;
        scanf ("%d%d",&n,&m);
        int nb=m*0.8;
        if (4*m%5) nb++;//!注意
        int mark=0,val;
        for (int i=1; i<=n; i++){
            int x;
            scanf ("%d",&x);
            a[i]=x;
            if (i==9) val=x;
            if (i==9 && x>=nb) mark=1;
        }
        sort(a+1,a+1+n,cmp);
        if (mark) printf("Yes
    ");
        else {
            if (val>=a[3]) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    View Code

    J.牛牛战队的秀场

    题目大意:给你正n边形和其外接圆的半径,问你从第i个顶点到第j个顶点的最短路径是多少(编号是从1开始顺时针编号)

    示例

    输入

    4 1
    1 2

    输出

    1.414214

    题目理解错了,我以为只能顺时针走。。。。然后卡了好久。。。我们先算出这个正n边形的边长,这个很好算:

     n边形可以分解成n个一模一样的等腰三角形,一个等腰三角形又可以拆成2个一模一样的直角三角形,那么角1的度数就很好算了:$angle 1=frac{360}{2n}=frac{pi }{n}$

    那么根据三角函数,$x$也就出来了:$x=2rsinangle 1$

    最后我们取顺时针到j点和逆时针到j点的最小值

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
      
    const double pi=acos(-1);
      
    int main(int argc, char const *argv[])
    {
        int n,r;
        scanf ("%d%d",&n,&r);
        int i,j;
        scanf ("%d%d",&i,&j);
        double a=pi/n;
        double len=2.0*r*sin(a);
        double ans1,ans2;
         
        ans1=len*n;
        ans1-=1.0*abs(i-j)*len;
     
        ans2=1.0*abs(i-j)*len;
     
        printf("%.7f
    ",min(ans1,ans2));
        return 0;
    }
    View Code
    路漫漫兮
  • 相关阅读:
    NPOI 的使用心得
    uploadfiy 动态传递Form 参数
    积分系统总结
    easyui dataBox 增加一天,减少一天
    easyui datagrid footer 页脚问题
    sql server 视图 的一个例子
    sql server int 列 NULLIF,isnull 判断是0还是1 ,如果是0就变成1
    easyui 小知识
    获取 日期 最后一天
    my97 日期控件
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/12305068.html
Copyright © 2020-2023  润新知