北京师范大学第十七届程序设计竞赛决赛-重现赛

版权声明: https://blog.csdn.net/baidu_41671472/article/details/90143457

鉴于博主是个铁憨憨,忘了还有比赛故只做了三题QAQ,后期补

足球

题目描述

足球是世界第一大运动。
有人曾以这样的方式来评价一直球队的能力:
球队能力等于球队球员的总身价乘以该球队身价最低一人的身价。
现在已知每支球队都有 23 人,且球员的身价不超过 1000,不低于 1,
你需要求出每支球队的能力值。

输入描述:

第一行是一个正整数T (T <= 20),表示有T只队伍。
接下来T行,每行包含 23 个范围均不超过1000的正整数 ,表示一支球队所有队员的身价。

输出描述:

对每支球队输出一行,表示这支的能力值。

输入

1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

输出

23

如题

#include <iostream>
#include <algorithm>
using namespace std;

int main(){
    
    int T;
    cin >> T;
    while(T--){
        long long int mmin = 10010;
        long long int s = 0;
        for(int i=0; i<23; i++){
            long long int t;
            cin >> t;
            s += t;
            mmin = min(mmin, t);
        }
        cout << mmin * s << endl;
    }
    
    return 0;
}

进制

题目描述

给一个长度不超过 18 的 01 串,你需要输出这个串在 2, 3, 4, 5, 6, 7, 8, 9, 10 进制表示下的数值在 10 进制下的和。

输入描述:

第一行是一个正整数 T (T<=100000),表示测试数据的组数,

接下来 T 行,每行包含一个长度不超过 18 的 01 串,保证没有前导零。
输出描述:
对于每组测试数据,输出一个整数。

输入

2
10
101

输出

54
393

Atoi 就是转换函数,再按照题目要求

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
 
unsigned long long int Atoi(string s,int radix)    //s是给定的radix进制字符串
{
    unsigned long long int ans=0;
    for(int i=0;i<s.size();i++)
    {
        char t=s[i];
        if(t>='0'&&t<='9') ans=ans*radix+t-'0';
        else ans=ans*radix+t-'a'+10;
    }
    return ans;
}
 
int main(){
    int T;
    cin >> T;
    while(T--){
        string s;
        cin >> s;
        unsigned long long int sum = 0;
        for(int i=2; i<=10; i++){
            sum += Atoi(s, i);
        }
        cout << sum << endl;
    }
     
    return 0;
}

选数字

题目描述

给一个长为 n 的序列 a1,a2,…,an,从中等概率选出 k 个下标不同的数字,求最小值的期望值。 不难发现期望值乘以Ckn之后是一个整数,你只需要输出这个整数对 1000000007 取模后的结果。 这里Ckn表示从 n 个数中无序选出 k 个数的方案数,也就是组合数。

输入描述:

第一行是一个正整数T(T≤20),表示测试数据的组数,对于每组测试数据,
第一行是两个正整数 n,k(n≤1000,k≤n),分别表示序列长度以及选出的数字个数。
第二行包含n个整数ai(0≤ai≤1000)。

输出描述:

对于每组测试数据,输出一行,包含一个整数,表示期望值乘以
Ckn之后对 1000000007 取模的结果。

输入

1
5 2
1 2 3 4 5

输出

20

  • 样例的计算顺序:

    1. 计算出C(5, 2)
    2. 选中1,从右边四个数中选择一个数,共有4种选法,其概率是4/ C 5 2 C_5^2
    3. 选中2,从右边三个数中选择一个数,共有3种选法,其概率是3/ C 5 2 C_5^2
    4. 选中3,从右边两个数中选择一个数,共有2种选法,其概率是2/ C 5 2 C_5^2
    5. 选中4,从右边一个数中选择一个数,共有1中选法,其概率是1/ C 5 2 C_5^2
    6. 期望是 [1*4/ C 5 2 C_5^2 + 2*3/C(5,2) + 3*2/ C 5 2 C_5^2 + 4*1/ C 5 2 C_5^2 ] * C 5 2 C_5^2
    7. 结果是 期望* C 5 2 C_5^2 = 1*4/ C 5 2 C_5^2 + 2*3/ C 5 2 C_5^2 + 3*2/ C 5 2 C_5^2 + 4*1/ C 5 2 C_5^2
  • 通过上述的计算顺序不难发现,不需要求出 C 5 2 C_5^2 ,因为最后会被约掉

  • 我的计算方法是:

    1. 现将数组 a 从小到大排序
    2. 从第一个数开始遍历
    3. 将被遍历到的数作为最小的数,再从其右边的数中选择k-1个数,使其构成k个数
    4. 最后的结果就是 i = 1 N a [ i ] C n i k 1 \sum_{i=1}^Na[i]*C_{n-i}^{k-1}
  • 组合数的计算公式:这里用的是最简单的计算公式 C i j C_i^j = C i 1 j C_{i-1}^j + C i 1 j 1 C_{i-1}^{j-1} 打表计算,节省时间。

  • 这里打表时间是 1000*1000,输入+计算的时间是T*n

#include <iostream>
#include <algorithm>
using namespace std;
 
const int maxLen = 1010;
const int mod = 1000000007;
unsigned long long int Mix[maxLen][maxLen];
 
void init(){
    for(int i=0; i<maxLen; i++){
        Mix[0][i] = 0;
        Mix[i][0] = 1;
    }
    for(int i=1; i<maxLen; i++)
        for(int j=1; j<maxLen; j++)
            Mix[i][j] = (Mix[i-1][j] + Mix[i-1][j-1])%mod;
}
int x[maxLen];
int main(){
    init();
    int T;
    cin >> T;
    while(T--){
        int n, k;
        cin >> n >> k;
        for(int i=0; i<n; i++){
            cin >> x[i];
        }
        sort(x, x+n);
        unsigned long long int sum = 0;
        for(int i=0; i<n; i++){
            if(n-i-1 < k-1)
                break;
            sum += (x[i]*Mix[n-i-1][k-1]);
            sum %= mod;
        }
        cout << sum << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/baidu_41671472/article/details/90143457