编程珠玑笔记-第12章习题
1 ,rand的返回值最大值是7fff
使用位操作产生大的随机值
View Code
int bigRand() { return rand()<<15&rand(); } int rand(int l,int u) { int k=(rand()%3)<<30&(rand()<<15)&rand(); return l+k%(u-l+1); }
2,随机选取0-n之间的一个i,取i,i+m-1共m个数,结果取模
3,m<n/2时,从n取一个数,在集合中的概率小于1/2,因此取值次数的期望是2
这里题目的描述并不严谨
4,总共要取m次,集合的大小从0,1,2...m-1,次数的期望分别是n/n,n/(n-1),n/(n-2)...n/(n-m+1)
当m=n时,和大概是nln(n)
7,第一问:添加一个最大值,输出时用最大值减一下,ps,如果m很大肯定会栈溢出
View Code
void randselect(int m,int n,int nMax) { if(m>0) { if(rand()%n<m) { printf("%d\n",nMax-n+1); randselect(m-1,n-1,nMax); }else randselect(m,n-1,nMax); } }
第二问:每一个元素要么选要么不选,递归产生所有的情况
View Code
void randselect(int m,int n,vector<int> p) { if(m>0) { if(n>m) randselect(m,n-1,p); p.push_back(n-1); randselect(m-1,n-1,p); }else { for (int i=0;i<p.size();i++) { printf("%d ",p[i]); } printf("\n"); } } int main() { vector<int> t; randselect(2,10,t); system("pause"); return 1; }
8,产生有顺序的数,然后混合一下,书后答案是生成后就输出,这个答案比较靠谱..
基于集合的算法可以使用比如multiset保存数
直接生成m个数
9,使用Floyd的生成算法
可以证明每个元素被选到的概率相等
10,这个题目是看明白了,答案看不明白,谷歌一下终于明白了
答案的意思是说不断读取下一行,同时保存一个变量x指示当前应选择的行
在第n行时有1/n的概率将x设为n
可以用递归证明取每一行的概率都是1/n
11,其实就是3在12后面的概率,因为不用考虑其他元素,这个概率是1/3
12,话说我没找到它说的那个m=0就会崩溃的程序,知道作者指的是哪个程序,我觉的作者的意思是某个历史上的程序如何如何,我觉得这里翻译得不大好,有些歧义
测试方法:可以生成大量数据进行统计