2025dsfz Day1 杂题做题记录
【位运算】801. 二进制中1的个数
- 使用
lowbit查找出二进制中 \(1\) 的个数
int lowbit(int x){
return x & -x;//-x具有较高优先级
}
每次进行 lowbit ,然后减去 lowbit(x) 直到为 \(0\)。减的次数即为答案。
//学校垃圾评测机需要吸氧O3
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n;
cin>>n;
while(n--){
int k,a = 0;
cin>>k;
while(k > 0) k -= (k&-k),a++;//内嵌lowbit
cout<<a<<" ";
}
}
三分
点击展开题面

- 直接套三分模版。
如何求 \(lmid,rmid\) :
double lm = l + (r - l) / 3.0;
double rm = r - (r - l) / 3.0;
- Warning:需要求的是函数的\(y\) 值!
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-5;
double f(double x) {
return (exp(x) + exp(-x)) / 2 + x;
}
int main() {
double l, r;
cin >> l >> r;
while (abs(l - r) > eps) {
double lm = l + (r - l) / 3.0;
double rm = r - (r - l) / 3.0;
// cout << lm << " " << rm << endl;
if (f(lm) > f(rm)) {
l = lm;
} else {
r = rm;
}
}
cout << fixed << setprecision(4) << f(l);
}
哈希
- 详见之前的blogs
朴素哈希(unordered_map)
【哈希表】840. 模拟散列表
//速通整活版
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-5;
unordered_map <int,int> mp;
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int q;
char op;
int x;
cin>>q;
while(q--){
cin>>op>>x;
if(op == 'I'){
mp[x]++;
}else cout<<((mp[x] == 0) ? "No" : "Yes")<<"\n";
}
}
字符串哈希
- 之前的博客有讲过。
- 这次注意的点:在求 \(char\) 类型数组长度的时候如果下表从 \(1\) 开始就要写成
strlen(char+1)而不是唐氏的strlen(char)-1。
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
const int P = 131;
char s[1000100];
unsigned long long/*!Important!*/ h[1010100], p[1010000];
void gethash() {
int len = strlen(s+1)/*!Important!*/;
p[0] = 1;//!Important!
for (int i = 1; i <= len; i++) {
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + s[i];
}
}
unsigned long long get11(int l, int r) {
return h[r] - h[l - 1] * p[r - l + 1];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, q;
cin >> n >> q>> (s + 1);
gethash();
for(int i = 1;i <= q;i++){
int a,b,c,d;
cin>>a>>b>>c>>d;
if(get11(a,b) == get11(c,d)){
cout<<"Yes\n";
}else{
cout<<"No\n";
}
}
}
二分
数的三次方根
- tips: 这里不放标准解法了,水一发立方根函数
double cbrt(double x)。直接求x的三次方根。
#include <bits/stdc++.h>
using namespace std;
int main(){
double x;
cin>>x;
cout<<fixed<<setprecision(4)<<cbrt(x);
}
P2678 [NOIP 2015 提高组] 跳石头
- 题解见Here,这个写的很有实力
- Warning:如果你过不了样例,可能是你二分的 \(l\) 和输入的 \(l\) 重名了。

#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define int long long
int n, m, d;
int a[50010];
bool check(int mid){
int tot = 0,i = 0,now = 0;
while(i < n+1){
i++;
if(a[i]-a[now] < mid) tot++;
else now = i;
}
return tot <= m;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> d >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
a[n+1] = d;
int l = 1, r = d,ans = 0;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1,ans = mid;
else r = mid - 1;
}
cout<<ans;
}
离散化
【离散化】802. 区间和
- 一开始打桶排序前缀和的时候循环范围没设置好导致发生了一些TLE的莫名错误
- 然后吸氧+关同步流过了一半,WA。
- 然后数组开小了。
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define int long long
int c[N], a[N], b1[N], b2[N], d[2*N]/*!!!Danger!!!: 至少3e5*/;
int ton[5 * N];
int k, n, q;
vector<int> v;
signed main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> c[i];
v.push_back(a[i]);
}
for (int i = 1; i <= q; i++) {
cin >> b1[i] >> b2[i];
v.push_back(b1[i]);
v.push_back(b2[i]);
}
for (int i = 0; i < v.size(); i++) {
d[i+1] = v[i];
}
sort(d + 1, d + 1 + v.size());
k = unique(d + 1, d + 1 + v.size()) - d - 1;
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(d + 1, d + 1 + k, a[i]) - d;
ton[a[i]] += c[i];
}
for (int i = 1; i <= k/*!!!Danger!!!*/; i++) {
ton[i] += ton[i - 1];
}
for (int i = 1; i <= q; i++) {
b1[i] = lower_bound(d + 1, d + 1 + k, b1[i]) - d;
b2[i] = lower_bound(d + 1, d + 1 + k, b2[i]) - d;
cout<<ton[b2[i]]-ton[b1[i]-1]<<"\n";
}
}

浙公网安备 33010602011771号