CSP-J模拟赛day4——解析+答案

二进制加减法

题解

显然我们可以发现,在二进制下 2 n 2^n 2n这个结果在二进制下就是1后面 n n n个0所以如果仅有 2 a + 2 b 2^a+2^b 2a+2b这个运算,那么在二进制下这个运算结果只会包含两个1
所以会影响1个数的就是这个 − 2 c -2^c 2c,手动模拟后就会发现最后答案为 b − c + 1 b-c+1 bc+1
这里要注意数据范围,记得开 l o n g l o n g long long longlong

Code

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

int main(){
	long long a,b,c;
	cin>>a>>b>>c;
	cout<<b-c+1; 
	return 0;
}

反码转换

题解

送分题,按题意模拟即可

Code

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

int main(){
	string a;
	cin>>a;
	if (a[0]=='0')cout<<a;
	else {
		cout<<a[0];
		for (int i=1;i<a.length();i++){
			if (a[i]=='0')cout<<'1';
			else cout<<'0';
		}
	}
	return 0;
}

密码匹配

题解

这道题显然是不可能模拟的,所以必然思路依旧是找循环节,但是对于两个互质的 l e n ( a ) , l e n ( b ) len(a),len(b) len(a),len(b) l c m lcm lcm 依旧会达到 l e n ( a ) × l e n ( b ) len(a)\times len(b) len(a)×len(b)
那么问题就在于如何快速处理出循环节中能匹配上的数量,这里可以通过自己举例模拟一下两个互质长度的字符串,看匹配情况
会发现能够匹配得上的 a [ i ] a[i] a[i] b [ i ] b[i] b[i] 必然满足 i % g c d ( l e n ( a ) , l e n ( b ) ) i \% gcd(len(a),len(b)) i%gcd(len(a),len(b))相同,也就是说对于 a , b a,b a,b长度的 g c d gcd gcd取模余数相同的位置才有机会配对去比较
那么我们完全可以将 a , b a,b a,b中所有的字符按照 % g c d ( l e n ( a ) , l e n ( b ) ) \% gcd(len(a),len(b)) %gcd(len(a),len(b))的余数进行处理,只有余数相同的位置需要比较
而因为字符串仅由小写字母构成,所以我们完全可以记录一下在某个余数下,每个字母的出现
次数,然后根据乘法原理直接计算答案
这样的话复杂度即为 O ( l e n ( a ) + l e n ( b ) ) O(len(a)+len(b)) O(len(a)+len(b))

Code

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

long long n, m;
int ls, lt, c;
char s[1001000], t[1001000];
long long cnt[30], ans;
int main(){
	cin>>n>>m;
	cin>>s>>t; 
	ls = strlen(s);
	lt = strlen(t);
	c = __gcd(ls, lt);
	for (int i = 0; i < c; i++){
		memset(cnt, 0, sizeof(cnt));
		for (int j = 0; j < ls / c; j++){
			cnt[s[j * c + i] - 'a']++;
		}
		for (int j = 0; j < lt / c; j++){
			ans += cnt[t[j * c + i] - 'a'];
		}
	}
	ans *= (n * c) / lt;
	cout<<ans;
	return 0;
}

比赛安排

题解

很容易发现,这是个二分问题,云桌面服务器越多越容易满足所有人,越少越满足不了那就直接二分需要多少台云桌面服务器然后 c h e c k check check即可
c h e c k check check的过程可以发现,就是一个队列模拟的过程,先让前 m i d mid mid个人进入队列,由于每个人模拟赛的时间都是 m m m
所以结束顺序一定是按照入队顺序来的,那每次就只需要拿队头跟当前第 i i i个人比较一下时间即可
总体复杂度 O ( n l o g n ) O(nlogn) O(nlogn)显然是没有问题的

Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
long long a[maxn], b[maxn], n, m;
bool check(int mid){
	queue<long long>q;//用来存储机子的数量 
	for(int i = 1; i <= n; i++){
		if(q.size() < mid){	
			q.push(a[i] + m);//判断机子的数量够不够当前这个答案的数量 
		}else{
			long long now = q.front();
			q.pop();
			if(now > a[i] + b[i]){//如果当前这个点不符合 
				return false;
			}
			q.push(max(now, a[i]) + m);//将合适的值放进去 
		}
	}
	return true;
}
int main(){
	cin >> n >> m;
	for(int i = 1; i <= n; i++){
		cin >> a[i] >> b[i];
	}
	int l = 1, r = n, ans;
	while(l <= r){//利用二分答案找答案 
		int mid = (l + r) / 2;
		if(check(mid)){
			ans = mid;
			r = mid - 1;
		}else{
			l = mid + 1;
		}
	}
	cout << ans << endl;
	return 0;
}

CSP将至,各位读者如果是有什么问题的,都可以评论,留言,或者私信我都可以的,蟹蟹~~

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值