190801测试-总结(题目-题解)


title: 190801测试-总结(题目-题解)
date: 2019-08-02 14:35:13
tags:

  • 入门
  • 高精度
  • 动态规划
  • 博弈论
    categories: 题解
    mathjax: true

欢迎访问我的博客,以获得更好的阅读体验Hunter’s Blog

20190802的上机测试题目和题解!!

1.判断素数个数

题目描述

输入两个整数和,输出两者之间的素数个数(包括 X X X Y Y Y

输入格式

两个整数和 X X X Y Y Y
( 1 < = X , Y < = 1 0 5 1<=X,Y<=10^5 1<=X,Y<=105)

输出格式

输出一个整数,表示 X X X Y Y Y之间的素数个数(包括 X X X Y Y Y

样例

样例输入
1 100
样例输出
25

注意点:有坑😭 X X X不一定大于 Y Y Y

题解:

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

bool p(int x) {
    bool f = 1;
    for (int i = 2; i <= sqrt(x); i++)
        if (x % i == 0) {
            f = 0;
            break;
        }
    return f;
}

int main() {
    // freopen("prime.in","r",stdin);
    // freopen("prime.out","w",stdout);
    int x, y;
    cin >> x >> y;//有问题就交换一下
    if (x > y)
        swap(x, y);
    int ans = 0;
    for (int i = x; i <= y; i++)
        if (p(i) && i != 1)
            ans++;
    cout << ans;
    return 0;
}

2.火车调度序列统计

就是Catalan数(虽然知道但是还是没有AC

题目描述

有辆各不相同的火车在车道上等待出站(火车的两端都可以当动力源),火车进站前可以通过一个调度站调整火车出站次序,调度站不限定所能停放的火车数量,每次只能进或出一辆火车。请你编程求出辆火车的不同出站序列的总数。

输入格式

一个数 n , ( 1 < = n < = 1000 ) n,(1<=n<=1000) n,(1<=n<=1000)

输出格式

一个数,即可能输出序列的总数目。

样例

样例输入
3
样例输出
5

题解:

公式+高精度

C ( n ) = ( 2 n ) ! n ! ( n + 1 ) ! C(n) = \frac{(2n)!}{n!(n+1)!} C(n)=n!(n+1)!(2n)!

以上公式可以化成

C ( n ) = ( n + 2 ) ⋅ ( n + 3 ) ⋅ ( n + 4 ) ⋅ ⋅ ⋅ ( 2 n − 1 ) ⋅ ( 2 n ) n ! C(n) = \frac{(n+2)\cdot(n+3)\cdot(n+4)\cdot\cdot\cdot(2n-1)\cdot(2n)}{n!} C(n)=n!(n+2)(n+3)(n+4)(2n1)(2n)
考的时候没有推出公式 所以就GG了
代码

#include <iostream>
#include <cstdio>

using namespace std;

int a[100001],h=1;


int main()
{
    int n;
    a[0]=1;
    cin>>n;
    
    for (int i=n+2;i<=n*2;i++)//高精度乘单精度
    {
        for (int j=0;j<h;j++)
            a[j]*=i;
        for (int j=0;j<100001;j++)//进位处理
        if (a[j]/10>0) {
            a[j+1]+=a[j]/10;
            a[j]=a[j]%10;
        }
        h=100001;
        while (a[h]==0) h--;//扫一遍找h
        h++;
    }

    for (int i=2;i<=n;i++) //高精度除单精度
    {
        for (int j=h-1;j>=0;j--)
        {
            if (a[j]%i!=0)
                a[j-1]+=10*(a[j]%i);
            a[j]=a[j]/i;
        }
    }
    h=100001;
    while (a[h]==0) h--;//扫一遍找h
    for (int i=h;i>=0;i--)//输出
        cout<<a[i];
}

贪心的小精灵

题目描述

圣诞节到了,一个小精灵想在圣诞树上拿到小礼物。圣诞树一共有 n n n层高,在圣诞树的第 k k k层,一共有个 k k k放置礼物的礼物点,每个礼物点有对应的礼物数量。 ( 1 < = k < = n ) (1<=k<=n) (1<=k<=n)。小精灵必须从圣诞树的最顶端(1,1)开始拿礼物,每层只能拿从一个礼物点拿对应数量的礼物。小精灵很懒,他每次只会向距离最近的礼物点前进。圣诞树上有个特殊的礼物点,那里的礼物是小精灵必须要拿到的。小精灵既想要经过特殊点,又想要在圣诞树上拿到最多的礼物,请你帮他算出他最多能拿到多少个礼物。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xjUeV4tr-1580477513215)(https://i.loli.net/2019/08/02/5d43c0cb30e6068092.png)]

输入格式

第1行只有一个整数 n n n,表示 n n n层圣诞树;

第2到 n + 1 n+1 n+1行,每层每个礼物点的礼物数量,数字之间有一个空格;

n + 2 n+2 n+2行有两个数 x x x y y y,表示小精灵必须要经过的礼物点,即第 x x x层的第 y y y个礼物点。

输出格式

礼物数量总和的最大值

样例

样例输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
2 2
样例输出
28

题解

两边动态规划 就是从上往下和从下往上两次DP
这样求出从(1,1)到必经点的最大和必经点到底部的最大
然后就AC啦

代码如下:

#include <iostream>
#include <cstdio>

using namespace std;

int a[103][103],ft[103][103],fb[103][103];

int main()
{
    //freopen("gift.in","r",stdin);
    //freopen("gift.out","w",stdout);
    int n,x,y;
    cin>>n;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=i;j++)
            cin>>a[i][j];
    cin>>x>>y;
    for (int i=1;i<=n;i++)//从上往下 ft[x][y]是从上往下到x,y的最大收获
        for (int j=1;j<=i;j++)
            ft[i][j]=max(ft[i-1][j],ft[i-1][j-1])+a[i][j];
    for (int i=n;i>=1;i--)//从下往上 fb[x][y]是从下往上到x,y的最大收获
        for (int j=i;j>=1;j--)
            fb[i][j]=max(fb[i+1][j],fb[i+1][j+1])+a[i][j];
    /*这些是测试的输出  莫得感情的
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=i;j++)
            cout<<ft[i][j]<<" ";
        cout<<endl;
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=i;j++)
            cout<<fb[i][j]<<" ";
        cout<<endl;
    }*/
    cout<<ft[x][y]+fb[x][y]-a[x][y];
    return 0;
}

取火柴游戏

→题目在这←

描述

和Nim的石子游戏一摸一样 只是石头变成了火柴

关于Nim游戏可以看这里 Nim游戏

就是说 对于每一种形式 都是必胜态与必败态中的一个
并且每个必胜态肯定存在使情况变为必败态的移动策略
而每个必败态无论如何移动都会让局面成为必胜态

这是代码↓

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    int n;
    cin>>n;
    int a[n+2],tmp=0;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        tmp=tmp ^ a[i];
    }
    if (tmp==0) {
        cout<<"lose";
        return 0;
    }
    int k;
    for (int i=1;i<=n;i++)
        if ((a[i]^tmp)<=a[i])
            {k=i;break;}
    cout<<a[k]-(a[k]^tmp)<<" "<<k<<endl;
    a[k]=a[k]^tmp;
    for (int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    return 0;
}

十二号诛杀者

介于懒得复制题目(太多用公式大的复制不了)

题目链接

这道题30分

使用Dijkstra最短路

代码如下 极丑无比


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <memory.h>
#include <iomanip>

using namespace std;

bool book[600];

int main()
{
    freopen("killer.in","r",stdin);
    freopen("killer.out","w",stdout);
    int n,m,q1,q2,q3,s,u,v,w,l,r,a,b,c,d;
    int e[502][502];
    cin>>n>>m>>q1>>q2>>q3>>s;
    int f[n+3];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        e[i][j]=2147483647;
    for (int i=1;i<=m;i++)
    {
        cin>>u>>v>>w;
        e[u][v]=w;
    }
    for (int i=1;i<=q1;i++)
    {
        cin>>u>>l>>r>>w;
        for (int j=l;j<=r;j++)
            if (w<e[u][j])
                e[u][j]=w;
    }
    for (int i=1;i<=q2;i++)
    {
        cin>>l>>r>>v>>w;
        for (int j=l;j<=r;j++)
            if (w<e[j][v])
                e[j][v]=w;
    }
    for (int i=1;i<=q3;i++)
    {
        cin>>a>>b>>c>>d>>w;
        for (int j=a;j<=b;j++)
            for (int k=c;k<=d;k++)
                if (w<e[j][k])
                    e[j][k]=w;
    }
    for(int i=1;i<=n;i++)
        e[i][i]=0;
    /*
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        cout<<setw(9)<<e[i][j]<<" ";
        cout<<endl;
    }
    */

    int k;

    for (int i=1;i<=n;i++)
        f[i]=e[s][i];
    for (int i=1;i<=n;i++)
    {
        int mi=2147483647;
        for (int j=1;j<=n;j++)
            if ((f[j]<mi)&&(book[j]==0))
            {
                mi=f[j];
                k=j;
            }
        book[k]=1;
        //cout<<mi<<" "<<k<<endl;
        for (int j=1;j<=n;j++)
            if (e[k][j]<2147483647)
                if (f[j]>f[k]+e[k][j])
                    f[j]=f[k]+e[k][j];
    }
    //for (int i=1;i<=n;i++)
    //    cout<<book[i]<<" ";
    //cout<<endl;
    for (int i=1;i<=n;i++)
        if (f[i]==2147483647) cout<<-1<<" ";
    else
        cout<<f[i]<<" ";
    return 0;
}


坐等讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值