【随机化】
【随机化】
能在若干次内随机试出且大概率正确
常用函数
rand
生成随机整数
使用时需要#include<cstdlib>
可用取模来规定大小
需要生成随机种子:srand(time(nullptr))
预定义随机数生成器
mt19937
类似于rand()
使用时用其定义一个随机数生成器:std::mt19937 myrand(seed)
seed 可不填,不填 seed 则会使用默认随机种子
#include<bits/stdc++.h>
using namespace std;
int main() {
mt19937 myrand(time(nullptr));
cout << myrand() << endl;
return 0;
}
minstd_rand0
线性同余生成器
$s_i \equiv s_{i-1} \times A + C $
#include<bits/stdc++.h>
using namespace std;
int main() {
minstd_rand0 rng;
rng.seed(chrono::steady_clock::now().time_since_epoch().count());
//rng():原始随机数
uniform_int_distribution<int> dist(1, 100);//范围随机数
return 0;
}
random_shuffle
随机打乱容器中元素的顺序
使用时需要#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
srand(time(0));
random_shuffle(nums.begin(), nums.end());
// 示例输出(每次不同):5 1 9 3 7 2 8 4 6
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int my_rand(int n) {
return rand() % n; // 基于 rand() 实现
}
int main() {
vector<char> chars = {'a', 'b', 'c', 'd', 'e'};
srand(time(0));
random_shuffle(chars.begin(), chars.end(), my_rand);
for (char c : chars) {
cout << c << " ";
}
// 示例输出:c e a b d
return 0;
}
例题整理
Colinear
证明随机可行+计算几何(直线一般式)
https://atcoder.jp/contests/abc422/tasks/abc422_e
题目大意
思路
代码
int n;
vector<i64> lineGeneralForm(i64 x1, i64 y1, i64 x2, i64 y2) {
// 处理两点重合的情况
if (x1 == x2 && y1 == y2) {
return {0, 0, 0}; // 两点重合,无法确定一条直线
}
// 计算A、B、C的初始值:已知两点求一般式
i64 A = y2 - y1;
i64 B = x1 - x2;
i64 C = x2 * y1 - x1 * y2;
// 计算最大公约数,用于化简
i64 g = gcd(llabs(A), gcd(llabs(B), llabs(C)));
if (g != 0) {
A /= g;
B /= g;
C /= g;
}
// 确保首项系数为正(约定)
if (A < 0 || (A == 0 && B < 0)) {
A = -A;
B = -B;
C = -C;
}
return {A, B, C};
}
void solve(){
cin>>n;
vector<P64> a(n+1);
for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].sc;
int cnt=100;
for(int i=1;i<=cnt;i++){
i64 p=rand()%n+1,q=rand()%n+1;
if(p==q) continue;
vector<i64> line=lineGeneralForm(a[p].fi,a[p].sc,a[q].fi,a[q].sc);
int cn=2;
for(int j=1;j<=n;j++){
if(j==p || j==q) continue;
if((line[0]*a[j].fi+line[1]*a[j].sc+line[2])==0){
cn++;
}
}
if(cn>n/2){
cout<<"Yes"<<endl;
for(auto son:line){
cout<<son<<" ";
}
cout<<endl;
return;
}
}
cout<<"No"<<endl;
}