特点:可能对,可能错,随机性,不确定性
数值随机算法
例1: 计算 pi 值?
思想:在一个正方形中画一个圆,随机产生很多个点,通过统计并计算在圆中的点的个数与所有点的比值来近似地计算 pi
Monte Carlo 方法,可以通过统计随机点在圆内的个数与总点数的比例来估算圆周率的值。
具体实现方法是,在正方形中随机生成大量点,计算这些点到正方形中心的距离,如果距离小于等于正方形边长的一半,则认为该点在正方形内,并判断该点是否在圆内。根据概率统计可知,圆内点数与总点数的比例应该近似于圆的面积与正方形面积的比例,即
通过求解可得 ,因此可以使用这个方法来估算圆周率的值。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int total = 1000000; // 总点数
int in_circle = 0; // 圆内点数
srand(time(NULL)); // 初始化随机数发生器
for (int i = 0; i < total; i++) {
// 在正方形内生成随机点
double x = rand() / (double)RAND_MAX * 2 - 1; // [-1, 1] 内的随机数
double y = rand() / (double)RAND_MAX * 2 - 1; // [-1, 1] 内的随机数
// 判断点是否在圆内
if (x * x + y * y <= 1) {
in_circle++;
}
}
// 计算圆周率
double pi = 4.0 * in_circle / total;
printf("Estimated pi: %f\n", pi);
return 0;
}
例2: 计算积分
- 方法一:随机投点法
- 好理解
在矩形中随机产生一些点,求落在蓝色区域的概率P,PXS=所求
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
double f(double x) {
return x * x; // 这里以f(x)=x^2举例
}
double calculusRand1(double a, double b, double M, int n) {
int k = 0; // 记录落在函数下方的随机点数
srand((unsigned)time(NULL)); // 初始化随机种子
for (int i = 1; i <= n; ++i) {
double x = a + (double)rand() / RAND_MAX * (b - a); // 在[a, b]之间随机产生x值
double y = (double)rand() / RAND_MAX * M; // 在[0, M]之间随机产生y值
if (y <= f(x)) k++; // 如果随机点(x, y)在函数下方,计数器k加1
}
double result = M * (b - a) * ((double)k / n); // 计算定积分近似值
return result;
}
int main() {
double a = 0, b = 1, M = 1;
int n = 1000000;
double result = calculusRand1(a, b, M, n);
printf("The definite integral of f(x) between %f and %f is approximately: %f\n", a, b, result);
return 0;
}
- 方法二:平均值方法
- 一个随机变量X 的数学期望 E(X)可以通过在 n次随机实验中观察值 x1,x2,...xn 的算数平均值 来近似
原理:
计算, 的期望,就ok了
对给定区间 [a,b] 进行随机抽样,并将抽样点代入函数 g(x) 进行计算。具体来说,我们可以使用 rand 函数生成 [a,b] 中的随机整数,然后计算对应的函数值 g(x),并将它累加到变量
I
中。最后,将(b-a)*I/n
作为结果返回即可
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double g(double x) {
}
int main() {
int n;
double a, b, I = 0.0;
scanf("%lf %lf %d", &a, &b, &n);
srand(time(NULL));
for (int i = 1; i <= n; i++) {
double x = a + (double)rand() / RAND_MAX * (b - a); // 生成随机抽样点
I += g(x); // 计算函数值,并累加到 I 中
}
double ans = (b - a) * I / n;
printf("%.6lf\n", ans);
return 0;
}
-
板子题
- 问题来源:codeforces 418 C Square Table (随机算法)
C. Square Table
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
While resting on the ship after the "Russian Code Cup" a boy named Misha invented an interesting game. He promised to give his quadrocopter to whoever will be the first one to make a rectangular table of size n × m, consisting of positive integers such that the sum of the squares of numbers for each row and each column was also a square.
Since checking the correctness of the table manually is difficult, Misha asks you to make each number in the table to not exceed 108.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 100) — the size of the table.
Output
Print the table that meets the condition: n lines containing m integers, separated by spaces. If there are multiple possible answers, you are allowed to print anyone. It is guaranteed that there exists at least one correct answer.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int IsSquare(int a) {
int k = (int)sqrt(a);
if (k * k == a) return 1;
return 0;
}
int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
int a, b, c, d;
while (2 > 1) {
a = rand() % 100 + 1;
b = rand() % 100 + 1;
c = rand() % 100 + 1;
d = rand() % 100 + 1;
int s1 = (m - 1) * a * a + b * b;
int s2 = (n - 1) * a * a + c * c;
int s3 = (m - 1) * c * c + d * d;
int s4 = (n - 1) * b * b + d * d;
if (IsSquare(s1) && IsSquare(s2) && IsSquare(s3) && IsSquare(s4)) {
break;
}
}
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < m - 1; j++) {
printf("%d ", a);
}
printf("%d\n", b);
}
for (int j = 0; j < m - 1; j++) {
printf("%d ", c);
}
printf("%d\n", d);
}
return 0;
}