2020 乐山师范学院程序设计大赛题解

2020 乐山师范学院程序设计大赛题解

比赛链接
交题要在题库搜索对应的题才能交

总结:

心态爆炸!!!

F FFi n t intint

C CCI N F INFINF

算完 E EE 的复杂度不敢写

心态爆炸

A: 好数对

题意:

给定一个长度为 n nna aa 数组, 如果存在一个下标 i , j , i < j i,j, i<ji,j,i<j 并且 a [ i ] = = a [ j ] a[i] == a[j]a[i]==a[j],就是好数对。求有多少个这样的数对

思路:

各种方法都行,直接通过下标计数法快速计算

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

int cnt[maxn];

int main()
{
    IOS();
    int n;
    ll ans = 0;
    cin >> n;
    for(int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        ans += cnt[x];
        ++cnt[x];
    }
    cout << ans << endl;
    
    return 0;
}

B: 设计网页

题意:

给定一个 n nn, 问是否能找到 a ∗ b = = n , a > 1 , b > 1 a*b == n, a>1,b>1ab==n,a>1,b>1

思路:

直接判断 n nn 是不是素数,因为素数的因子只有 1 11 和本身

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

int main()
{
    int n;
    cin >> n;
    int flag = 1;
    for(int i = 2; i*i <= n; ++i)
        if(n % i == 0) {
            flag = 0;
            break;
        }
    if(flag == 1) cout << "YES\n";
    else cout << "NO\n";
    return 0;
}

C: 最大乘积

题意:

给定长度为 n nn 的数组,问选 5 55 个数相乘最大可以的结果是多少

思路:

其实是分情况讨论,但分情况讨论写起来很麻烦,直接暴力就

将数组从小到大排序,

前面选 0 00 个, 后面选 5 55

前面选 1 11 个, 后面选 4 44

前面选 2 22 个, 后面选 3 33

前面选 5 55 个, 后面选 0 00

所有结果选一个最大值即可

数据范围超出了 i n t intint

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const ll INF = 0x3f3f3f3f3f3f3f3f;

const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

ll num[maxn];

int main()
{
    IOS();
    int T;
    cin >> T;
    while(T--) {
        int n;
        cin >> n;
        for(int i = 0; i < n; ++i)
            cin >> num[i];
        sort(num, num+n);
        ll ans = -INF;
        for(int i = 0; i <= 5; ++i) {
            ll sum = 1;
            for(int j = 0; j < i; ++j)
                sum *= num[j];
            for(int j = n-5+i; j < n; ++j)
                sum *= num[j];
            ans = max(ans, sum);
        }
        cout << ans << endl;
    }
    return 0;
}

D: 后缀语言

题意:

给定一个字符串,根据字符串的后缀判断是哪国语言

思路:

直接看最后一个字母就完了

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const ll INF = 0x3f3f3f3f3f3f3f3f;

const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

int main()
{
    IOS();
    int T;
    cin >> T;
    while(T--) {
        string s;
        cin >> s;
        char c = *s.rbegin();
        if(c == 'o') {
            cout << "FILIPINO\n";
        }
        else if(c == 'u') {
            cout << "JAPANESE\n";
        }
        else {
            cout << "KOREAN\n";
        }
    }
    return 0;
}

E: 分石头

题意:

给定一堆石头,每个石头都有重量,要求分成两堆,每堆之间的重量尽可能平均。

思路:

01 0101 背包,复杂度O ( n ∗ n ∗ w / 2 ) = 1.8 ∗ 1 0 8 O(n*n*w/2) = 1.8*10^8O(nnw/2)=1.8108

这题直接无语

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const ll INF = 0x3f3f3f3f3f3f3f3f;

const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

int dp[3000005];
int w[maxn];

int main()
{
    IOS();
    int n;
    cin >> n;
    int sum = 0;
    for(int i = 1; i <= n; ++i) {
        cin >> w[i];
        sum += w[i];
    }
    ll lim = sum/2;
    for(int i = 1; i <= n; ++i) {
        for(int j = lim; j >= w[i]; --j)
            dp[j] = max(dp[j], dp[j-w[i]]+w[i]);
    }
    ll ans = abs(sum-2*dp[lim]);
    cout << ans << endl;
    return 0;
}

F: 我的魔法

题意:

你有 a aa 个红宝石 b bb 个蓝宝石 c cc 个红蓝宝石,红蓝宝石可以相互转成红色或蓝色,现在你要消耗 x xx 个红宝石 y yy 个蓝宝石 z zz 个任意宝石,问够不够

思路:

先算红宝石够不够,不够从红蓝宝石扣除

如果够多余的就记着加到 s u m sumsum

蓝宝石同上

最后就是判断c > = 0 a n d s u m + c > = z c >= 0 and sum + c >= zc>=0andsum+c>=z

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

int main()
{
    IOS();
    ll a, b, c;
    ll x, y, z;
    cin >> a >> b >> c;
    cin >> x >> y >> z;
    ll sum = 0;
    if(a >= x)
        sum += a-x;
    else
        c -= x-a;
    if(b >= y)
        sum += b-y;
    else
        c -= y-b;
    if(c < 0 || c + sum < z) {
        cout << "There are no miracles in life\n";
    }
    else cout << "It is a kind of magic\n";
    
    
    return 0;
}

G: 最大公约数

题意:

给定一个数 n nn,另外任意整数 a aab bb 的最大公约数记为 g c d ( a , b ) gcd(a, b)gcd(a,b),求解从 1 11n nn 中的任意两个不相同的整数的最大公约数的最大值。

思路:

如果 n nn 是偶数,那么 a = n / 2 , b = n a = n/2, b = na=n/2,b=n,这样最大公因数就是 n / 2 n/2n/2,很明显这是最大的因为 a < b a < ba<b

如果 n nn 是奇数,那么 n − 1 n-1n1 是偶数,那就回到第一条,所以答案就是 n / 2 n/2n/2

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const ll INF = 0x3f3f3f3f3f3f3f3f;

const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

ll num[maxn];

int main()
{
    IOS();
    int T;
    cin >> T;
    while(T--) {
        int n;
        cin >> n;
        cout << n/2 << endl;
    }
    return 0;
}

H: 最小公倍数

题意:

给定一个整数 b bb,另外 a aa 表示 1 111 0 18 10^{18}1018 中的所有整数,计算式子 [ a , b ] / a [a, b] / a[a,b]/a 有多少个不同的结果,这里 [ a , b ] [a, b][a,b] 表示整数 a aa 与整数 b bb 的最小公倍数。

思路:

化解公式 求

l c m ( a , b ) / a = ( a ∗ b / g c d ( a , b ) ) / a = b / g c d ( a , b ) lcm(a,b)/a = (a*b/gcd(a,b))/a = b/gcd(a,b)lcm(a,b)/a=(ab/gcd(a,b))/a=b/gcd(a,b)

因为 a aa 取值范围超过 b bb,所以 g c d ( a , b ) gcd(a, b)gcd(a,b) 的结果就都是 b bb 的因子

所以答案就转换成求 b bb 有多少个因子

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

int main()
{
    IOS();
    ll b;
    cin >> b;
    ll cnt = 0;
    for(ll i = 1; i*i <= b; ++i) {
        if(b % i == 0) {
            ++cnt;
            if(b / i != i) ++cnt;
        }
    }
    cout << cnt << endl;
    
    return 0;
}

I: 绝对值游戏

题意:

有两个元素个数长度相等的数组 a aab bb , 每一轮都会从每个数组拿走一个数字,到最后只剩下一个数字结束。一个人希望剩下的数字绝对值之差最大,一个人希望最小,最后的绝对值是多少.

思路:

不管怎么操作一个数组总会剩下一个数,那么第二个人就会选择剩下对应绝对值最小的数,所以对第一个数组的每个数,第二个数组都能选到相应最小的,那答案很明显就是所有最小里面选最大的。

这其实就是对应关系,只要第一个数组不删这个数,那么第二个数组也不会删除让它答案最小的数,第一个删了第二个也就跟着删.

代码:

#include <bits/stdc++.h>
using namespace std;
#define me(a, b) memset(a, b, sizeof(a))
#define IOS() ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;

ll a[maxn], b[maxn];

int main()
{
    IOS();
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    for(int i = 0; i < n; ++i) {
        cin >> b[i];
    }
    ll ans = 0;
    for(int i = 0; i < n; ++i) {
        ll mi = INF;
        for(int j = 0; j < n; ++j)
            mi = min(mi, abs(a[i]-b[j]));
        ans = max(ans, mi);
    }
    cout << ans << endl;
    return 0;
}

版权声明:本文为weixin_43313475原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。