2022杭电暑期第二场个人题解

1002 C++ to Python

题意:把字符串中的 “(”, “)”, ","和数字输出。(签到题啊 直接上代码了)

#include<bits/stdc++.h>
using namespace std;
int n, m, k, t, T;
void solve(){
    string s;
    cin >> s;
    for(int i = 0; i < s.size(); i++){
        if(s[i] == '(' || s[i] == ')')    cout << s[i];
        if(s[i] >= '0' && s[i] <= '9')    cout << s[i];
        if(s[i] == ',')    cout << s[i];
        if(s[i] == '-')    cout << s[i];
    }
    cout << endl;
}
int main(){
    cin >> T;
    while(T--)
        solve();
    return 0;
}

1012 Luxury cruise ship

题意:每天能存7或31或365枚硬币,至少要几天能刚好凑够N元。

队友说暴力过的,我也没细看,脑壳子宕机ing~

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
    int t;
    cin >> t;
    ll n;
    while (t--) {
        cin >> n;
        ll cnt = n / 365;
        ll res = n / 365 - cnt;
        bool f = false;
        ll m = cnt * 365 + n % 365;
        for (ll i = cnt; i >= 0; i--) {
            for (ll j = (m - i * 365) / 31; j >= 0; j--) {
                if ((m - i * 365 - j * 31) % 7 == 0) {
                    res += i + j + (m - i * 365 - j * 31) / 7;
                    f = true;
                    break;
                }
            }
            if (f) break;
        }
        if (f) cout << res << endl;
        else cout << -1 << endl;
    }
    return 0; 
}

1009 ShuanQ

题意:已知加密公式及解密公式,求截获来的信息是否能解密。
首先我们注意到解密公式rawdata = encrypteddata × Q mod M
而题目已经告诉了我们encrypteddata 和 P,Q
因此我们只需要求出素数M即可。

那么问题来了,我们怎么求M呢?
我们发现 P × Q ≡ 1 mod M

因此我们只需要在 P × Q - 1中找出最大的素因子看符不符合即可。

为什么是最大的呢?

因为题目告诉我们 P,Q ,encrtpteddata < M

因此如果最大的素因子都不满足要求那么就没有满足要求的M了。

#include<bits/stdc++.h>

const int N = 3e6 + 1;
#define LL long long
using namespace std;
int n, m, k, t, T;
bool isprime[N];
int prime[N];
int j = 0;

void init(){//首先用素数筛筛出素数
	memset(isprime, true, sizeof isprime);
	for(int i = 2; i < N; i++){
		if(isprime[i])	prime[++j] = i;
		int k = 1;
		while(1){
			if(i * prime[k] > N)	break;
			isprime[i * prime[k]] = false;
			if(i % prime[k] == 0)	break;
			k++;
		}
	}
}

void solve(){
	LL p, q, en;
	cin >> p >> q >> en;
	LL m = p * q - 1;
	//priority_queue<long long> _q;
	LL ans = -1;
	for(int i = 1; i <= j; i++){
		if(m % prime[i] == 0){
			//_q.push(prime[i]);
			ans = max(ans, prime[i]);//如果是素因子我们就更新一下答案。
			while(m % prime[i] == 0)	m /= prime[i];
		}
	}
	//if(m > 1)	_q.push(m);
	if(m > 1)	ans = max(ans, m);
	
	if(ans > p && ans > q && ans > en)	cout << en * q % ans << endl;
	else	cout << "shuanQ\n";
}

int main(){
	init();
	cin >> T;
	while(T--)
		solve();
	return 0;
}

1007 Snatch Groceries

题目好长读题就读了半天

题意:给n个区间,问你按照时间顺序,在碰到第一个区间重叠之前有多少人能买到东西。

在写题的时候一群人都因读不懂题而抓狂我也是,在队友的帮助自己不懈的解读下才解决了。

首先我们给这n个区间按照2关键子排序,第一个关键字是区间的左端点,第二个关键字是区间长度。
这样我们碰到区间重叠的情况的时候直接退出就可以了。
感觉这题好水,就是题目看不懂

上代码。

#include<bits/stdc++.h>

using namespace std;
int n, m, k, t, T;

struct node{
	int l, r, len;
}f[100010];

bool cmp(node a, node b){
	if(a.l == b.l)	return a.len < b.len;
	return a.l < b.l;
}

void solve(){
	cin >> n;
	for(int i = 1, a, b; i <= n; i++){
		cin >> f[i].l >> f[i].r;
		f[i].len = f[i].r - f[i].l;
	}
	sort(f + 1, f + 1 + n, cmp);
	
	int cnt = 1;
	int r = f[1].r;
	for(int i = 2; i <= n; i++){
		cnt++;//这里我们假设每个区间都是合法的,如果碰到重叠的情况我们直接减去2就可以了。
		if(f[i].l > r)	r = f[i].r;
		else{
			cnt -= 2;
			break;
		}
	}
	
	cout << cnt << endl;
}

int main(){
	cin >> T;
	while(T--)
		solve();
	return 0;
}

1003 Copy

题意:给n个数,q次操作,操作1是复制区间[l, r]到r的后面,这里注意是r的后面而不是最后面,操作2是询问Xi的值,求所有的Xi的异或和。

一开始的思路直接就是模拟,但是由于范围太大直接被我们pass了。

不用模拟的方法是什么呢?

我们只需要记录下每一次复制的区间所在的范围和长度,然后搜索的时候遍历每个区间,看当前所在的位置是否是在那个区间的左边。
就拿样例来说

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

执行1 2 4操作之后 原数组就变成了 1 2 3 4 2 3 4 5(我们并不对原数组进行修改,就是说a5还是5)

那我们保存的时候这个区间就保存为[5, 7], len = 3;
如果搜索到[5, 8]时,我们直接减去区间长度,也就是3,就行了。
比如当X = 8时,8 > 5,那么我们让8 - 3 得5, 于是得到a5

#include<bits/stdc++.h>

using namespace std;
int n, m, k, t, T;
int a[100010];

struct node{
	int l, r, len;
}f[100010];

void solve(){
	cin >> n >> k;
	for(int i = 1; i <= n; i++)	cin >> a[i];
	
	int cnt = 0, ans = 0;
	while(k--){
		int op, l, r;
		cin >> op;
		if(op == 1){
			cin >> l >> r;
			cnt++;
			f[cnt].l = r + 1;//因为赋值的区间是紧接着[l, r]的,所以左端点应该是r + 1
			f[cnt].r = f[cnt].l + r - l;
			f[cnt].len = r - l + 1;
		}else{
			cin >> l;
			int pos = cnt;//从最新的区间开始往前判断
			while(pos){
				if(l < f[pos].l)	pos--;	//如果l在当前区间的左边就看下一个区间
                else	l -= f[pos--].len;	//如果l在当前区间的范围或者在右边, 就减去区间长度
			}
			ans ^= a[l];
		}
	}
	
	cout << ans << endl;
}

int main(){
	cin >> T;
	while(T--)
		solve();
	return 0;
}

第一次写题解,有写错的、写的不好的请指出。
后续还会不会有题解,得看我们队的实力了(我们太菜了QAQ)第一天就过了一题

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值