2018级《程序设计基础(B)II》期末上机考试( 题解)

  A [4522] - 学位证  
  B [4519] - 猜数游戏    
  C [4517] - easy math problem    
  D [4516] - 排队买饭    
  E [4520] - 射箭游戏    
 

F [4518] - 小D的棋盘

   
  G [4521] - 小D的一串数字

 

A学位证

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

众所周知,在山东理工大学拿到学位证是需要一定的学分绩点的,但是由于程序设计的日益重要,学校决定让某些程序设计成绩十分优秀但是总学分绩点不够的同学也拿到学位证。

现在已知拿到学位证所需的学分绩点 x 和程序设计的优秀分数线 y 和 n 个同学的成绩信息。

你能写一个程序输出可以拿到学位证的同学的姓名和学号么?

Input

第一行一个数字n,代表同学总数 (n<=1000)。

第二行开始 n 行每行分别输入第 i 个同学的学分绩点,程序设计成绩,姓名和学号,用空格分隔,学分绩点和程序设计成绩均在int范围内,姓名和学号为不超过11位的字符串

最后输入拿到学位证所需的绩点 x 和程序设计优秀线 y ( 1<=x , y <=1e9 )。

Output

按照输入顺序输出能拿到学位证的同学的姓名和学号。

合格的定义为总学分绩点合格程序设计成绩优秀。

Sample Input

3
50 50 goudan 18272727272
61 40 zhangsan 18110505050
50 80 lisi 1817272aaaa
60 70

Sample Output

zhangsan 18110505050
lisi 1817272aaaa
#include 

using namespace std;

int main()
{
    int a,i,b,c;
    int n[1010],m[1010];
    char s[1010][15],x[1010][15];
    cin >> a;
    for(i=1;i<=a;i++)
    {
        cin >> n[i] >> m[i] >> s[i] >> x[i];
    }
    cin >> b >> c;
    for(i=1;i<=a;i++)
    {
        if(n[i]>b||m[i]>c)
        {
            cout << s[i] << " " << x[i] << endl;
        }
    }
    return 0;
}

 

B猜数游戏

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

Alice 和 Bob 正在玩一个猜数游戏,游戏规则如下。

有且仅有一个未知的整数需要Alice去猜测,Bob事先已经知道了这个数。

在游戏中 Bob 总共提供给 Alice n 条线索,而Alice只有一次猜测机会。

每条线索由 L 和 R 两个整数组成,表示要猜测的数大于等于L,并且小于等于R。

Alice是足够聪明的,不过她希望你能告诉她,一次猜对的概率是多少。

(数据保证Bob给Alice提供的线索均是正确的)

Input

第一行输入一个正整数 T 表示数据的组数。(1 <= T <= 100)

每组开始输入一个正整数 n。(1 <= n <= 100) 

接下来 n 行,每行输入两个整数 L 和 R。 (-100 <= L <= R <= 100)

Output

输出共T行,第 i 行表示第 i 组测试数据的答案。 

答案用分数的形式(A/B)进行表示,注意不要输出多余的空格。

Sample Input

3
1
-100 100
2
3 4 
4 5
2
3 6
4 7

Sample Output

1/201
1/1
1/3
#include 

using namespace std;

int main()
{
    int a,i,b,x,y,t=0,mi,ma;
    int n[110],m[110],s[110];
    cin >> a;
    while(a--)
    {
        mi=110;
        ma=-110;
        cin >> b;
        if(b==1)
        {
            cin >> x >> y;
            s[++t]=y-x+1;
        }
        else
        {
            for(i=1; i<=b; i++)
            {
                cin >> n[i] >> m[i];
            }
            for(i=1; i<=b; i++)
            {
                if(mam[i])
                {
                    mi=m[i];
                }
            }
            s[++t]=mi-ma+1;
        }
    }
    for(i=1; i<=t; i++)
    {
        if(i==t)
        {
            cout << 1 << "/" << s[i];
        }
        else
        {
            cout << 1 << "/" << s[i] << endl;
        }
    }
    return 0;
}

 

Ceasy math problem

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

对于一个数n,有以下两种操作:

一是减一,需要花费 a 。

但是如果 n 能被 k 整除,还可以花费 b 让 n 除以 k。

请问将这个数变为1最少要多少花费?

Input

第一行一个整数n(n<=1e5)

第二行三个正整数分别为a, b, k ( 0 < a , b , k <= n ,n*a<1e9 ).

Output

输出一个整数代表最小花费。

Sample Input

10
1 2 2

Sample Output

6
#include 

using namespace std;

int main()
{
    long long int a,x,y,z,sum=0;
    cin >> a;
    cin >> x >> y >> z;
    while(a>1)
    {
        if(a%z==0)
        {
            if((a-(a/z))*x>y)
            {
                a=a/z;
                sum=sum+y;
            }
            else
            {
                a=a-1;
                sum=sum+x;
            }
        }
        else
        {
            a=a-1;
            sum=sum+x;
        }
    }
    cout << sum;
    return 0;
}

 

D排队买饭

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

理工大的食堂到了饭点人可以说是相当多了,按理来说排队的时候先来的同学应该会先走,但实际情况可能并不一样,我们注意到对于一个队列往往由以下两种操作组成

当输入 1 时:代表队列最左面的同学完成了买饭操作,由于他会帮他的好朋友一起买,所以买完饭后会叫上所有与他编号相同的好朋友一起走,如果输入1时队伍已经为空则不删除。换句话说,如果序列不为空则会在序列中删除最左边的一个元素和与之编号相同的所有元素,否则不删除。

当输入 2 时:代表编号为 b 的同学想要插队买饭,由于他与编号为 a 的同学是好朋友,他会插入到队列从左往右的第一个编号为 a 的同学右边,如果队伍中没有编号为 a 的同学,他就会伤心的离开。换句话说,会在队列的从左往右的第一个 a 后面插入一个 b,如果队列中没有 a 则不插入。

需要注意的是,每次操作后都需要你判断一下队列是否为空,如果为空则输出“EMPTY”。

最后一行输出所有操作后的序列。

Input

第一行一个数 n 代表初始时序列中的元素 ( n<=1e5)

第二行 n个 int 范围内的数,最多有1000个不同的。

第三行一个数 m 代表操作的次数。(m<=1e5)

后面m行每行第一个数代表操作种类。

如果操作为 2 则再输入两个数 a,b。

Output

对于每次操作,如果操作后队列为空,则输出"EMPTY"。

所有操作完成后输出最终的序列。

(最下方提示有补充测试样例)

Sample Input

6
1 1 4 3 1 2
3
2 4 5
1
1

Sample Output

5 3 2

Hint

补充样例:

input:

6
1 1 4 3 1 2
5
2 6 5
1
1
1
1

output:

EMPTY

#include 
#include 
using namespace std;

int n[1000010];

int main()
{
    int a,i,b,c,x,y,j,t;
    cin >> a;
    for(i=1; i<=a; i++)
    {
        cin >> n[i];
    }
    cin >> b;
    while(b--)
    {
        cin >> c;
        if(c==1)
        {
            t=n[1];
            for(i=a; i>0; i--)
            {
                if(n[i]==t)
                {
                    for(j=i; j> x >> y;
            for(i=1; i<=a; i++)
            {
                if(n[i]==x)
                {
                    for(j=a; j>i; j--)
                    {
                        n[j+1]=n[j];
                    }
                    a++;
                    n[i+1]=y;
                    break;
                }
            }
        }
        if(a==0)
        {
            cout << "EMPTY" << endl;;
        }
    }
    if(a!=0)
    {
        for(i=1; i<=a; i++)
        {
            if(i==a)
            {
                cout << n[i];
            }
            else
            {
                cout << n[i] << " ";
            }
        }
    }
    return 0;
}

 

#include"bits/stdc++.h"
using namespace std;
#define New (node *)malloc(sizeof(node))
struct node
{
    int data;
    node *next;
};
int main()
{
    int n;
    cin>>n;
    node *head=New;
    node *p=head;
    for(int i=1; i<=n; i++)
    {
        int x;
        cin>>x;
        node *t=New;
        t->data=x;
        t->next=0;
        p->next=t;
        p=t;
    }
    int m;
    cin>>m;
    while(m--)
    {
        int kd;
        cin>>kd;
        if(kd==1)
        {
            if(head->next == 0)
            {
                puts("EMPTY");
                continue;
            }
            else
            {
                int x=head->next->data;
                p=head;
                node *p2=head->next;
                while(p2)
                {
                    if(p2->data != x)
                    {
                        p->next=p2;
                        p=p2;
                    }
                    p2=p2->next;
                }
                p->next=0;

                if(head->next == 0)
                {
                    puts("EMPTY");
                    continue;
                }
            }
        }
        else
        {
            p = head->next;
            int l,r;
            int flag=0;
            cin >> l >> r;
            for(; p; p=p->next)
            {
                if(p->data == l)
                {
                    node *t=New;
                    t->data=r;
                    t->next=p->next;
                    p->next=t;
                    flag=1;
                    break;
                }
            }
            if(head->next==0)
            {
                puts("EMPTY");
            }
        }
    }
    p=head->next;
    for(; p; p=p->next)
    {
        cout << p->data << " ";
    }
    return 0;
}

 

E射箭游戏

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

Alice正在玩一个射箭游戏。

现在Alice有 N 枝不同的箭,每只箭有它的攻击力。

有 M 个怪物,每个怪物有它的生命值,击杀怪物后会掉落金币。

每只箭最多使用一次,每个怪物最多被攻击一次。

且为了“简单”起见,怪物掉落金币数等于其生命值

问Alice最多可以获得多少金币。

Input

输入数据共三行。

第一行有两个正整数N和M,分别表示箭的数量和怪物的数量。(1 <= N <= 1000000, 1 <= M <= 1000000)

第二行有N个正整数,第 i 个数表示第 i 枝箭的攻击力 。(1 <= 攻击力 <= 1000000000)

第三行有M个正整数,第 i 个数表示第 i 个怪物的生命值和掉落金币数 。 (1 <= 生命值 <= 1000000000)

友情提示:答案会超出int范围,请使用长整形 long long(%lld) 进行计算。

Output

输出一个整数,表示Alice最多可以获得多少金币。

Sample Input

5 5
1 4 5 7 9
2 10 8 6 4

Sample Output

20

快排

#include 
#include 
using namespace std;

long long int n[1000010],m[1000010];
int main()
{
    long long int a,b,i,j,sum=0;
    cin >> a >> b;
    for(i=1; i<=a; i++)
    {
        cin >> n[i];
    }
    for(i=1; i<=b; i++)
    {
        cin >> m[i];
    }
    sort(n+1,n+a+1);
    sort(m+1,m+b+1);
    for(i=a; i>0; i--)
    {
        for(j=b; j>0; j--)
        {
            if(n[i]>=m[j])
            {
                sum=sum+m[j];
                b=j-1;
                break;
            }
        }
    }
    cout << sum;
    return 0;
}

 

#include 
#include 
using namespace std;

long long int n[1000010],m[1000010];

void quick(long long int a[],int left,int right)
{
    int x=a[left],i=left,j=right;
    if(left>=right)
    {
        return;
    }
    while(i=x)
        {
            j--;
        }
        a[i]=a[j];
        while(i> a >> b;
    for(i=1; i<=a; i++)
    {
        cin >> n[i];
    }
    for(i=1; i<=b; i++)
    {
        cin >> m[i];
    }
    quick(n,1,a);
    quick(m,1,b);
    for(i=a; i>0; i--)
    {
        for(j=b; j>0; j--)
        {
            if(n[i]>=m[j])
            {
                sum=sum+m[j];
                b=j-1;
                break;
            }
        }
    }
    cout << sum;
    return 0;
}

 

F小D的棋盘

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

小D有一个神奇的棋盘,棋盘有n行,m列。这个棋盘为什么神奇呢?因为这个棋盘被施加了一个魔法,小D每念一次咒语,棋盘上的棋子就能分裂到相邻的上下左右四个格子上,分裂之后原来的会消失,如果他的某个方向上没有格子(比如第一行没有向上的格子),那么他就不会向上分裂。现在小D想知道他念了k次咒语之后棋盘上现在会有多少个棋子。注意:每个格子能够放无数个棋子,分裂后的棋子再念一次咒语棋子能继续分裂。

Input

输入n,m。(2<=n<=20,2<=m<=20)表示棋盘的行列。

接下来n行,每行m个数字aij(0<=aij<=1),每个数字代表这个格子初始的时候有几个棋子。

接下来一行输入k(1<=k<=10)。

Output

输出一个数字表示小D念了k次咒语之后棋盘上现在会有多少个棋子。这个数字保证在int的范围内。

Sample Input

3 3
0 0 0
0 1  0
0 0 0
2

Sample Output

12

Hint

在示例中,念了一次咒语后棋盘的情况是:

0 1 0

1 0 1

0 1 0

再念一次后棋盘的情况是:

2 0 2

0 4 0

2 0 2

最终棋盘有12个棋子。

#include 
#include 
using namespace std;

int main()
{
    int a,b,i,j,c,sum=0;
    int n[21][21],m[21][21];
    cin >> a >> b;
    for(i=1; i<=a; i++)
    {
        for(j=1; j<=b; j++)
        {
            cin >> n[i][j];
            m[i][j]=n[i][j];
        }
    }
    cin >> c;
    while(c--)
    {
        for(i=1; i<=a; i++)
        {
            for(j=1; j<=b; j++)
            {
                if(i==1&&j==1)
                {
                    n[i][j]=n[i][j]+m[i+1][j]+m[i][j+1];
                }
                else if(i==1&&j==b)
                {
                    n[i][j]=n[i][j]+m[i][j-1]+m[i+1][j];
                }
                else if(i==a&&j==1)
                {
                    n[i][j]=n[i][j]+m[i-1][j]+m[i][j+1];
                }
                else if(i==a&&j==b)
                {
                    n[i][j]=n[i][j]+m[i-1][j]+m[i][j-1];
                }
                else if(i!=1&&i!=a&&j==1)
                {
                    n[i][j]=n[i][j]+m[i-1][j]+m[i][j+1]+m[i+1][j];
                }
                else if(i!=1&&i!=a&&j==b)
                {
                    n[i][j]=n[i][j]+m[i-1][j]+m[i][j-1]+m[i+1][j];
                }
                else if(j!=1&&j!=b&&i==1)
                {
                    n[i][j]=n[i][j]+m[i][j-1]+m[i][j+1]+m[i+1][j];
                }
                else if(j!=1&&j!=b&&i==a)
                {
                    n[i][j]=n[i][j]+m[i][j-1]+m[i][j+1]+m[i-1][j];
                }
                else
                {
                    n[i][j]=n[i][j]+m[i][j-1]+m[i][j+1]+m[i-1][j]+m[i+1][j];
                }
            }
        }
        for(i=1; i<=a; i++)
        {
            for(j=1; j<=b; j++)
            {
                n[i][j]=n[i][j]-m[i][j];
                m[i][j]=n[i][j];
            }
        }
    }
    for(i=1; i<=a; i++)
    {
        for(j=1; j<=b; j++)
        {
            if(n[i][j]!=0)
            {
                sum=sum+n[i][j];
            }
        }
    }
    cout << sum;
    return 0;
}
#include 
int dp[2][20][20];
int main()
{
    int n,m,q;
    scanf("%d%d",&n,&m);
    for(int i=0; i

 

G小D的一串数字

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

小D在纸上随便写了两串数字,“23333333”,“0123456789”。第一个串中含有7个重复的相邻的数字,第二个串中不含相邻的重复的数字。小D喜欢第一类串,但是他放低了要求,只要一串数字中含有超过两个重复的相邻的数字,小D就喜欢这串数字。现在他想知道,长度为n的的所有数字串,最多有多少个串会被他喜欢?但是小D是个数学白痴,麻烦你帮他解决这个问题。

Input

输入一个N,(3=

Output

输出一个整数,表示小D最多喜欢多少串。

Sample Input

3

Sample Output

10

Hint

样例中111,222,333,444,555,666,777,888,999,000,这10个串是被小D喜欢的。

#include"bits/stdc++.h"
using namespace std;

typedef long long ll;

int n;
ll dp[20][20][20][20];

int dfs(int x,int ll,int l,int tr)
{
    if(x>n)
    {
        if(tr)
        {
            return 1;
        }
        return 0;
    }
    if(~dp[x][ll][l][tr])
    {
        return dp[x][ll][l][tr];
    }
    long long res=0;
    for(int i=0; i<=9; i++)
    {
        if(i==l && l==ll)
        {
            res += dfs(x+1,l,i,1);
        }
        else
        {
            res += dfs(x+1,l,i,tr);
        }
    }
    return dp[x][ll][l][tr] = res;
}

int main()
{
    cin >> n;
    memset(dp,-1,sizeof dp);
    cout<
#include 
int dp[50][50];

int main()
{
    int n,j,i;
    for(i=0; i<10; i++)
    {
        dp[1][i]=1;
    }
    scanf("%d",&n);
    for(i=2; i<=n; i++)
    {
        for(j=0; j<10; j++)
        {
            for(int k=0; k<10; k++)
            {
                if(j!=k)
                {
                    dp[i][j]+=dp[i-1][k]+dp[i-1][k+10];
                }
            }
            dp[i][j+10]=dp[i-1][j];
            dp[i][j+20]=dp[i-1][j+10]+dp[i-1][j+20]*10;
        }
    }
    int ans=0;
    for(int i=0; i<10; i++)
    {
        ans+=dp[n][i+20];
    }
    printf("%d\n",ans);
}

 

你可能感兴趣的:(期末考试)