PAT 520 钻石争霸赛真题(2020-05-20)题解 #后三题

7-6 随机输一次 (20分)

现要求你编写一个控制赢面的程序,根据对方的出招,给出对应的赢招。但是!为了不让对方意识到你在控制结果,你需要隔 K 次输一次,其中 K 是系统设定的随机数。

输入格式:

输入首先在第一行给出正整数 N(≤10),随后给出 N 个系统产生的不超过 10 的正随机数 { K1,K2,⋯,KN },数字间以空格分隔。这意味着第 i(i=0,1,⋯,N−1)次输局之后应该隔 Ki+1 次再让下一个输局。如果对方出招太多,则随机数按顺序循环使用。例如在样例中,系统产生了 3 个随机数 {2, 4, 1},则你需要:赢 2 次,输 1 次;赢 4 次,输 1 次;赢 1 次,输 1 次;然后再次回到第 1 个随机数,赢 2 次,输 1 次。

之后每行给出对方的一次出招:“ChuiZi”代表“锤子”、“JianDao”代表“剪刀”、“Bu”代表“布”。“End”代表输入结束,这一行不要作为出招处理。输入保证对方至少出了一招。

输出格式:

对每一个输入的出招,按要求输出赢或输局的招式。每招占一行。

输入样例:

3 2 4 1
ChuiZi
JianDao
Bu
JianDao
Bu
ChuiZi
ChuiZi
ChuiZi
JianDao
Bu
JianDao
Bu
ChuiZi
End

输出样例:

Bu
ChuiZi
ChuiZi
ChuiZi
JianDao
Bu
Bu
JianDao
ChuiZi
ChuiZi
ChuiZi
JianDao
JianDao

思路

判断flag是否等于a[cnt%N],这样模拟的思路最简单。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e6+10;

int a[100];

void win(string x) {
    if (x == "ChuiZi") cout << "Bu\n";
    else if (x == "JianDao") cout << "ChuiZi\n";
    else cout << "JianDao\n";
}

void lose(string x) {
    if (x == "ChuiZi") cout << "JianDao\n";
    else if (x == "JianDao") cout << "Bu\n";
    else cout << "ChuiZi\n";
}

int main() {
//     freopen("in.txt","r",stdin);

    int N;
    cin>>N;
    for (int i=0;i<N;i++) {
        cin>>a[i];
    }
    int flag=0,cnt=0;
    string s;
    while (cin>>s&&s!="End") {
        if (flag==a[cnt%N]) {
            lose(s);
            flag=0;
            cnt++;
        } else {
            win(s);
            flag++;
        }
    }
    return 0;
}

7-7 阶乘的非零尾数 (20分)

7-7 阶乘的非零尾数 (20分)

“求 N 阶乘末尾的第一个非零数字”是一道常见的企业笔试题。这里我们略微做个变化,求 N 阶乘末尾的第一个非零 K 位数,同时输出末尾有多少个零。

输入格式:

输入给出一个不超过 107 的正整数 N 和要求输出的位数 0<K<10。

输出格式:

在一行中输出 N 阶乘末尾的第一个非零 K 位数(注意前导零也要输出)、以及末尾 0 的个数,其间以 1 个空格分隔。

输入样例:

18 5

输出样例:

05728 3

思路

先把所有的5和2剔除,然后把漏掉的5 或 2再乘上去。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const long long MAXN = 1e6 + 10;

int main()
{
    // freopen("in.txt", "r", stdin);

    long long N, K;
    cin >> N >> K;
    long long base = 1;
    for (long long i = 0; i < K; i++)
    {
        base *= 10;
    }
    long long cnt2 = 0, cnt5 = 0, num = 1;
    for (long long i = 1; i <= N; i++)
    {
        long long m = i;
        while (m % 5 == 0) { m /= 5; cnt5++; }
        while (m % 2 == 0) { m/=2; cnt2++; }
        num*=m;
        num%=base;
    }
    long long cnt=min(cnt2,cnt5);
    for (long long i=0;i<cnt2-cnt;i++) { num=2ll*num%base; }
    for (long long i=0;i<cnt5-cnt;i++) { num=5ll*num%base; }
    long long tmp=num,bits=0;
    while (tmp) {
        bits++;
        tmp/=10;
    }
    for (long long i=0;i<K-bits;i++) { cout<<"0"; }
    cout<<num<<" "<<cnt<<endl;
    return 0;
}

7-8 三足鼎立 (25分)

当三个国家中的任何两国实力之和都大于第三国的时候,这三个国家互相结盟就呈“三足鼎立”之势,这种状态是最稳定的。

现已知本国的实力值,又给出 n 个其他国家的实力值。我们需要从这 n 个国家中找 2 个结盟,以成三足鼎立。有多少种选择呢?

输入格式:

输入首先在第一行给出 2 个正整数 n(2≤n≤105)和 P(≤109),分别为其他国家的个数、以及本国的实力值。随后一行给出 n 个正整数,表示n 个其他国家的实力值。每个数值不超过 109,数字间以空格分隔。

输出格式:

在一行中输出本国结盟选择的个数。

输入样例:

7 30
42 16 2 51 92 27 35

输出样例:

9

样例解释:

能联合的另外 2 个国家的 9 种选择分别为:

{16, 27}, {16, 35}, {16, 42}, {27, 35}, {27, 42}, {27, 51}, {35, 42}, {35, 51}, {42, 51}。

思路

  • 如果p不是最大,则满足条件的是小于a[i]+p的数
  • 如果p是最大 , 则满足条件的是大于p-a[i]的数

用lower_bound是为了多计入一位,这样避免x==y,x-y=0。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e5+10;

long long a[MAXN];
int main() {
//     freopen("in.txt","r",stdin);

    long long N,P;
    cin>>N>>P;
    for (int i=0;i<N;i++) {
        cin>>a[i];
    }
    long long ans=0;
    sort(a,a+N);
    for (int i=0;i<N;i++) {
        long long x=lower_bound(a+i+1,a+N,a[i]+P)-a;
        long long y=upper_bound(a+i+1,a+N,P-a[i])-a;
        ans+=max(0ll,x-y);
    }
    cout<<ans<<endl;
    return 0;
}
posted @ 2020-05-27 18:37  xyee  阅读(1059)  评论(0编辑  收藏  举报