(算法)等概率选出m个整数

题目:

从大小为n的整数数组A中随机选出m个整数,要求每个元素被选中的概率相同。

思路:

n选m,等概率情况下,每个数被选中的概率为m/n。

方法:

初始化:从A中选择前m个元素作为初始数组;

随机选择:从第m个元素开始,依次遍历数组下标i,并通过随机生成器生成数字k(生成0~n),如果k<m,则将A[i]替换A[k]。

证明:

归纳法:假设数组A大小为n,需要选m个元素,每个元素被选中的概率为m/n。

对于初始化的m个元素而言,其选中的概率自然为m/n;

而对于第n+1个元素,该元素被选中的概率m/(n+1)(根据随机生成器),

而对于此时前m个元素,根据第n+1个元素的选中与否情况:

第n+1个没选中的概率为1-m/(n+1),则全部留下的可能性为P1:m/n*(1-m/n+1),

第n+1个被选中的概率为m/(n+1)有一个被替换后留下的可能性为P2:m/n*m/(n+1)*(m-1)/m,

总的留下概率为:P1+P2=m/(n+1)

因此得证。

代码:

#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<vector>

using namespace std;

void pickM(const vector<int> &A,int m,vector<int> &pick){
    int n=A.size();

    for(int i=0;i<m;i++){
        pick.push_back(A[i]);
    }

    srand((unsigned)time(0));
    for(int i=m;i<n;i++){
        int k=rand()%n;
        if(k<m)
            pick[k]=A[i];
    }
}

int main(){
    int m,n;
    while(cin>>n>>m){
        vector<int> A(n);
        for(int i=0;i<n;i++)
            cin>>A[i];

        vector<int> pick;
        pickM(A,m,pick);        

        for(int i=0;i<m;i++)
            cout<<pick[i]<<" ";
        cout<<endl;
    }
    return 0;
}
时间: 2024-12-18 18:32:31

(算法)等概率选出m个整数的相关文章

算法笔记_155:算法提高 概率计算(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 生成n个∈[a,b]的随机整数,输出它们的和为x的概率. 输入格式 一行输入四个整数依次为n,a,b,x,用空格分隔. 输出格式 输出一行包含一个小数位和为x的概率,小数点后保留四位小数 样例输入 2 1 3 4 样例输出 0.3333 数据规模和约定 对于50%的数据,n≤5. 对于100%的数据,n≤100,b≤100. 2 解决方案 下面代码在系统中运行评分为90分,第五组数据无法通过,我用同版本的C代码运行(PS:具体参见文末

[算法]:分治法-求大整数相乘

#问题大整数相乘 #思路说明 对于大整数计算,一般都要用某种方法转化,否则会溢出.但是python无此担忧了. Python支持**"无限精度"的整数,**一般情况下不用考虑整数溢出的问题,而且Python Int类型与任意精度的Long整数类可以无缝转换,超过Int 范围的情况都将转换成Long类型. 例如: >>> 2899887676637907866*1788778992788348277389943 51872581574157002360341697913

算法笔记01--归纳法之整数幂

整数幂 算法1:对实数x的n次幂设计一个有效的算法.一种直接的方法是对x用迭代方法自乘n次,这种方法十分低效,因为它需要O(n)乘法.一个高效的方法可以用如下方法推出,令m=n/2,假设已经知道如何计算x^m.那么有两种情况:如果n是偶数,那么x^n = (x^m)^2:否则x^n = x(x^m)^2. 算法2:令n的二进制表示为dn-1.....d1,d0.从y=1开始,由n的高位至地位扫描,如果二进制数字为0,就对y平方:如果为1就对y平方并乘x.这就产生了递归算法EXPREC. 时间复杂

用蒙特卡洛算法解概率相关的路线规划问题

写给小陈~ 参考文献: Chou X., Gambardella L.M., Montemanni R. (2018) Monte Carlo Sampling for the Probabilistic Orienteering Problem. In: Daniele P., Scrimali L. (eds) New Trends in Emerging Complex Real Life Problems. AIRO Springer Series, vol 1. Springer -

蓝桥杯算法训练 出现次数最多的整数、

很简单,但有一个坑点,题目说了n是大于0且不超过20的整数: 但它的第六.七组数据n<0 n>20;所以加个判断就能过了: 下面是两种方法: #include<iostream> #include<map> using namespace std; int main() { int n;cin >> n; if(n>0&&n<=20) { map<int,int>p; int m; for(int i=0;i<n

4.6算法之贪心-3528:最小新整数

描述 给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0.n的位数为m.现在从m位中删除k位(0<k < m),求生成的新整数最小为多少?例如: n = 9128456, k = 2, 则生成的新整数最小为12456 输入第一行t, 表示有t组数据:接下来t行,每一行表示一组测试数据,每组测试数据包含两个数字n, k.输出t行,每行一个数字,表示从n中删除k位后得到的最小整数.样例输入 2 9128456 2 1444 3 样例输出 12456

微软算法100题20 字符串转整数 atoi

第20 题:题目:输入一个表示整数的字符串,把该字符串转换成整数并输出.例如输入字符串"345",则输出整数345 思路:atoi 主要考虑的是对输入的校验和边界处理,以及处理正负符号等 1 package com.rui.microsoft; 2 3 public class Test20_String2Int { 4 5 public static void main(String[] args) { 6 int sum = Test20_String2Int.convert(&q

[算法练习] 把字符串转换成整数

题目说明: 输入一个表示整数的字符串,把该字符串转换成整数并输出.例如输入字符串"345",则输出整数345. 程序代码: #include <gtest/gtest.h> using namespace std; int StrToInt(const char* szValue, int nBase = 0, bool* bValid = NULL) { long long nValue = 0; int nSign = 1; if (bValid) { *bValid

(算法)从0到n整数中数字2出现的次数

题目: 数出0到n(含)中数字2出现了几次. 思路: 1.暴力方法,数出每个数字包含几个2,然后累加起来. 2.分析:分别考虑数字n每一位出现2的次数,如123123: 从左往右考虑4123123: 考虑第一个1(即第6位),该位出现2的次数为4*10^6/10: 考虑第一个2(即第5位),该位出现2的次数为41*10^5/10+3123+1: 考虑第一个3(即第4位),该位出现2的次数为(412+1)*10^4/10: 附:除以10的原因在于:每10个数字,任意位出现2的概率为1/10. 总结