二进制加减法
题解
显然我们可以发现,在二进制下
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
b−c+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将至,各位读者如果是有什么问题的,都可以评论,留言,或者私信我都可以的,蟹蟹~~