2022年暑假训练赛(哈理工)

目录

A - 寂寞如雪

B - 吃雪糕

F - 奇怪的魔法

G - 荣誉击杀 


A - 寂寞如雪

原题链接 : https://ac.nowcoder.com/acm/contest/37895/A

题意:在给定的字符串中截取一段字符串来使用,然后在截取的字符串上按照奇数孤独段和偶数孤独段计算出该子串的孤独值,问:如何截取可以使得子串的孤独值最大

思路:首先找出给定字符串的所有的孤独段,并记录下长度(因为0对其没有用,可以直接忽略),然后对子串进行枚举,依次寻找最大的孤独值(切记这里不可使用前缀和,因为是按照截取之后的子串来规定奇数和偶数孤独段的,所以需要一次枚举判断, 注意数据范围)

代码模板:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;

string s;
ll a[N];
ll f[N];

int main() {
    cin >> s;
    s += '0';
    int len = 0, ans = 0;
    
    for (int i = 0; i < s.size(); i ++ ) {
        if(s[i] == '1') len ++ ;
        else if(s[i] == '0' && s[i - 1] == '1'){
            a[ ++ ans] = len;
            len = 0;
        }
    }
    
    ll maxx = 0;
    for (int i = 1; i <= ans; i ++ ) {
        int sum = 0;
        int cnt = 1;
        for (int j = i; j <= ans; j ++ ) {
            ll temp = a[j] * a[j];
            if(cnt % 2 == 0) {
                temp = -temp;
            }
            cnt ++ ;
            sum += temp;
            if(sum < 0) break;//退出循环,尽可能的减少循环次数
            
            if(maxx < sum) {
                maxx = sum;
            }
        }
    } 
    
    printf("%lld", maxx);
    
    
    return 0;
}

B - 吃雪糕

原题链接 :https://ac.nowcoder.com/acm/contest/37895/B

题意:按照规定aiaj<2^k 规定 ai 和 aj 是具有相似的口味(其中 表示进行异或),问:最多可以吃多少连续的区域并且没有相似口味的雪糕

思路:在给出的规定中可以改成二进制进行判断,即可将公式转换成 将数字 ai 和 aj 按照二进制数字将其向有移动k为,所得连个数若是不相同则满足aiaj >= 2^k ,反之就是不满足,就是具有相似口味(切记不可使用暴力直接进行判断,数据范围比较大,时间不满足)

代码模板:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5;
int a[N];
int n, k;
int f[N];
map<int, int> mp;

int main() {
    scanf("%d%d", &n, &k);
    
    for (int i = 1; i <= n; i ++ ) {
        scanf("%d", &a[i]);
        f[i] = a[i] >> k;
    }
    
    int len = 0;
    int maxx = 0;
    for (int i = 1; i <= n; i ++ ) {
        if(mp[f[i]] == 0) {
            mp[f[i]] = i;
            len ++ ;
        }
        else {
        	int temp = mp[f[i]]; 
            mp.clear();
        	len = 0;
            for (int j = temp + 1; j <= i; j ++) {
                mp[f[j]] = j;
                len ++ ;
            }
        }
//        cout << len << endl;
        maxx = max(maxx, len);
    }
    
    printf("%d\n", maxx);
    
    
    
    
    return 0;
}

F - 奇怪的魔法

原题链接 : https://ac.nowcoder.com/acm/contest/37895/F

题意 : 当数组中最大值是K的时候,找出所以的单调非递减的数据的组成方式,按照规定计算出总价值(一个数组的价值就是以k为最大值的数组的方案数 * k (最大值))

思路:可以看出这个是个组合数问题 分析的对于i  <= k 的总价值是 i * C(i, n + i - 1)(证明之后在补上),求组合数使用了快速幂

由于数据比较大所以需要对 1e9 + 7 进行取模,涉及了除法的取模,这里都补充一下(其中除法和减法最特别)

取模
1.加法取模:   (A+B)%P=(A%P+B%P)%P;
2.乘法取模      (AB)%P=(A%PB%P)%P;
3.减法取模:(A-B)%P=(A%P-B%P+P)%P; 要加上*P;
4.整除取模:费马小定理:(A\B\P)(A/B)%P=(A%P * B^(P-2)%P)%P:

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, k;
const int mod = 1e9 + 7; 

//快速幂
ll qpow(ll m, ll k) {
	ll res = 1 % mod, t = m;
	
	while (k) {
		if(k & 1) res = res * t % mod;
		t = t * t % mod;
		k >>= 1;
	}
	
	return res;
}

int main() {
	cin >> n >> k;
	
	ll ans = n;
	ll temp = n;
	
	for (ll i = 1; i < k; i ++ ) {
        //其中包含了除法的取余运算
		temp = ((temp * (n + i) % mod) % mod * qpow(i, mod - 2) % mod) % mod;
		ans = (ans % mod + temp % mod) % mod;
	}
	
	cout << ans << endl;
	
	
	return 0;
} 

G - 荣誉击杀

原题链接 :https://ac.nowcoder.com/acm/contest/37895/G

思路:一个简单的贪心题(签到题),并不难

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int a[N];
int n;
int l, r;

map<int, bool> mp;

int main() {
    scanf("%d", &n);
    
    for (int i = 1; i <= n; i ++ ) {
        scanf("%d", &a[i]);
        mp[a[i]] = true;
    }
    
    scanf("%d%d",&l, &r);
    
    ll sum = 0;
    
    for (int i = r; i >= l; i -- ) {
        if(mp[i]) {
            sum += i;
            break;
        }
    }
    sum += r;
    printf("%lld\n", sum);
    
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值