[Dr.Lib]Note:Math – Probabilities 概率

Via http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=probabilities

It has been said that life is a school of probability. A major effect of probability theory on everyday life is in risk assessment. Let's suppose you have an exam and you are not so well prepared. There are 20 possible subjects, but you only had time to prepare for 15. If two subjects are given, what chances do you have to be familiar with both? This is an example of a simple question inspired by the world in which we live today. Life is a very complex chain of events and almost everything can be imagined in terms of probabilities.

Gambling has become part of our lives and it is an area in which probability theory is obviously involved. Although gambling had existed since time immemorial, it was not until the seventeenth century that the mathematical foundations finally became established. It all started with a simple question directed to Blaise Pascal by Chevalier, a nobleman that gambled frequently to increase his wealth. The question was whether a double six could be obtained on twenty-four rolls of two dice.

As far as TopCoder problems are concerned, they're inspired by reality. You are presented with many situations, and you are explained the rules of many games. While it's easy to recognize a problem that deals with probability computations, the solution may not be obvious at all. This is partly because probabilities are often overlooked for not being a common theme in programming contests. But it is not true and TopCoder has plenty of them! Knowing how to approach such problems is a big advantage in TopCoder competitions and this article is to help you prepare for this topic.

Before applying the necessary algorithms to solve these problems, you first need some mathematical understanding. The next chapter presents the basic principles of probability. If you already have some experience in this area, you might want to skip this part and go to the following chapter: Step by Step Probability Computation. After that it follows a short discussion on Randomized Algorithms and in the end there is a list with the available problems on TopCoder. This last part is probably the most important. Practice is the key!

Basics
Working with probabilities is much like conducting an experiment. An outcome is the result of an experiment or other situation involving uncertainty. The set of all possible outcomes of a probability experiment is called a sample space. Each possible result of such a study is represented by one and only one point in the sample space, which is usually denoted by S. Let's consider the following experiments:

Rolling a die once
Sample space S = {1, 2, 3, 4, 5, 6}
Tossing two coins
Sample space S = {(Heads, Heads), (Heads, Tails), (Tails, Heads), (Tails, Tails)}

We define an event as any collection of outcomes of an experiment. Thus, an event is a subset of the sample space S. If we denote an event by E, we could say that E⊆S. If an event consists of a single outcome in the sample space, it is called a simple event. Events which consist of more than one outcome are called compound events.

What we are actually interested in is the probability of a certain event to occur, or P(E). By definition, P(E) is a real number between 0 and 1, where 0 denotes the impossible event and 1 denotes the certain event (or the whole sample space).

As stated earlier, each possible outcome is represented by exactly one point in the sample space. This leads us to the following formula:

That is, the probability of an event to occur is calculated by dividing the number of favorable outcomes (according to the event E) by the total number of outcomes (according to the sample space S). In order to represent the relationships among events, you can apply the known principles of set theory. Consider the experiment of rolling a die once. As we have seen previously, the sample space is S = {1, 2, 3, 4, 5, 6}. Let's now consider the following events:

Event A = 'score > 3' = {4, 5, 6}
Event B = 'score is odd' = {1, 3, 5}
Event C = 'score is 7' = ∅
A∪B ='the score is > 3 or odd or both' = {1, 3, 4, 5, 6}
A∩B ='the score is > 3 and odd' = {5}
A' = 'event A does not occur' = {1, 2, 3}

We have:

P(A∪B) = 5/6
P(A∩B) = 1/6
P(A') = 1 – P(A) = 1 – 1/2 = 1/2
P(C) = 0

The first step when trying to solve a probability problem is to be able to recognize the sample space. After that, you basically have to determine the number of favorable outcomes. This is the classical approach, but the way we implement it may vary from problem to problem. Let's take a look at QuizShow (SRM 223, Div 1 – Easy). The key to solving this problem is to take into account all the possibilities, which are not too many. After a short analysis, we determine the sample space to be the following:

S = { (wager 1 is wrong, wager 2 is wrong, you are wrong),
(wager 1 is wrong, wager 2 is wrong, you are right),
(wager 1 is wrong, wager 2 is right, you are wrong),
(wager 1 is wrong, wager 2 is right, you are right),
(wager 1 is right, wager 2 is wrong, you are wrong),
(wager 1 is right, wager 2 is wrong, you are right),
(wager 1 is right, wager 2 is right, you are wrong),
(wager 1 is right, wager 2 is right, you are right) }

The problem asks you to find a wager that maximizes the number of favorable outcomes. In order to compute the number of favorable outcomes for a certain wager, we need to determine how many points the three players end with for each of the 8 possible outcomes. The idea is illustrated in the following program:

Another good problem to start with is PipeCuts (SRM 233, Div 1 – Easy). This can be solved in a similar manner. There is a finite number of outcomes and all you need to do is to consider them one by one.

Let's now consider a series of n independent events: E1, E2, … , En. Two surprisingly common questions that may appear (and many of you have already encountered) are the following:

  1. What is the probability that all events will occur?
  2. What is the probability that at least one event will occur?

To answer the first question, we relate to the occurrence of the first event (call it E1). If E1 does not occur, the hypothesis can no longer be fulfilled. Thus, it must be inferred that E1 occurs with a probability of P(E1). This means there is a P(E1) chance we need to check for the occurrence of the next event (call it E2). The event E2 occurs with a probability of P(E2) and we can continue this process in the same manner. Because probability is by definition a real number between 0 and 1, we can synthesize the probability that all events will occur in the following formula:

The best way to answer the second question is to first determine the probability that no event will occur and then, take the complement. We have:

These formulae are very useful and you should try to understand them well before you move.

BirthdayOdds
A good example to illustrate the probability concepts discussed earlier is the classical "Birthday Paradox". It has been shown that if there are at least 23 people in a room, there is a more than 50% chance that at least two of them will share the same birthday. While this is not a paradox in the real sense of the word, it is a mathematical truth that contradicts common intuition. The TopCoder problem asks you to find the minimum number of people in order to be more than minOdds% sure that at least two of them have the same birthday. One of the first things to notice about this problem is that it is much easier to solve the complementary problem: "What is the probability that N randomly selected people have all different birthdays?". The strategy is to start with an empty room and put people in the room one by one, comparing their birthdays with those of them already in the room:

This so called "Birthday Paradox" has many real world applications and one of them is described in the TopCoder problem called Collision (SRM 153, Div 1 – Medium). The algorithm is practically the same, but one has to be careful about the events that may alter the sample space.

Sometimes a probability problem can be quite tricky. As we have seen before, the 'Birthday Paradox' tends to contradict our common sense. But the formulas prove to us that the answer is indeed correct. Formulas can help, but to become a master of probabilities you need one more ingredient: "number sense" . This is partly innate ability and partly learned ability acquired through practice. Take this quiz to assess your number sense and to also become familiar with some of the common probability misconceptions.

Step by Step Probability Computation
In this chapter we will discuss some real TopCoder problems in which the occurrence of an event is influenced by occurrences of previous events. We can think of it as a graph in which the nodes are events and the edges are dependencies between them. This is a somewhat forced analogy, but the way we compute the probabilities for different events is similar to the way we traverse the nodes of a graph. We start from the root, which is the initial state and has a probability of 1. Then, as we consider different scenarios, the probability is distributed accordingly.

NestedRandomness
This problem looked daunting to some people, but for those who figured it out, it was just a matter of a few lines. For the first step, it is clear what do we have to do: the function random(N) is called and it returns a random integer uniformly distributed in the range 0 to N-1. Thus, every integer in this interval has a probability of 1/N to occur. If we consider all these outcomes as input for the next step, we can determine all the outcomes of the random(random(N)) call. To understand this better, let's work out the case when N = 4.

  • After the first nesting all integers have the same probability to occur, which is 1 / 4.
  • For the second nesting there is a 1/4 chance for each of the following functions to be called: random(0), random(1), random(2) and random(3). Random(0) produces an error, random(1) returns 0, random (2) returns 0 or 1 (each with a probability of 1/2) and random(3) returns 0, 1 or 2.
  • As a result, for the third nesting, random(0) has a probability of 1/4 + 1/8 + 1/12 of being called, random(1) has a probability of 1/8 + 1/12 of being called and random(2) has a probability of 1/12 of being called.
  • Analogously, for the fourth nesting, the function random(0) has a probability of 1/4 of being called, while random(1) has a probability of 1/24.
  • As for the fifth nesting, we can only call random(0), which produces an error. The whole process is described in the picture to the right.

NestedRandomness for N = 4

The source code for this problem is given below:

If you got the taste for this problem, here are another five you may want to try:

ChessKnight – assign each square a probability and for every move check the squares one by one to compute the probabilities for the next move.
DiceThrows – determine the probability of each possible outcome for both players and then compare the results.
RockSkipping – the same approach, just make sure you got the lake pattern correctly.
PointSystem – represent the event space as a matrix of possible scores (x, y).
VolleyBall – similar to PointSystem, but the scores may go up pretty high.

Let's now take a look at another TopCoder problem, GeneticCrossover, which deals with conditional probability. Here, you are asked to predict the quality of an animal, based on the genes it inherits from its parents. Considering the problem description, there are two situations that may occur: a gene does not depend on another gene, or a gene is dependent.

For the first case, consider p the probability that the gene is to be expressed dominantly. There are only 4 cases to consider:

  • at least one parent has two dominant genes. (p = 1)
  • each parent has exactly one dominant gene. (p = 0.5)
  • one parent has one dominant gene and the other has only recessive genes (p = 0.25)
  • both parents have two recessive genes (p = 0)

Now let's take the case when a gene is dependent on another. This make things a bit trickier as the "parent" gene may also depend on another and so on … To determine the probability that a dependent gene is dominant, we take the events that each gene in the chain (starting with the current gene) is dominant. In order for the current gene to be expressed dominantly, we need all these events to occur. To do this, we take the product of probabilities for each individual event in the chain. The algorithm works recursively. Here is the complete source code for this problem:

See also ProbabilityTree.

Randomized Algorithms
We call randomized algorithms those algorithms that use random numbers to make decisions during their execution. Unlike deterministic algorithms that for a fixed input always give the same output and the same running-time, a randomized algorithm behaves differently from execution to execution. Basically, we distinguish two kind of randomized algorithms:

  1. Monte Carlo algorithms: may sometimes produce an incorrect solution – we bound the probability of failure.
  2. Las Vegas algorithms: always give the correct solution, the only variation is the running time – we study the distribution of the running time.

Read these lecture notes from the College of Engineering at UIUC for an example of how these algorithms work.

The main goal of randomized algorithms is to build faster, and perhaps simpler solutions. Being able to tackle "harder" problems is also a benefit of randomized algorithms. As a result, these algorithms have become a research topic of major interest and have already been utilized to more easily solve many different problems.

An interesting question is whether such an algorithm may become useful in TopCoder competitions. Some problems have many possible solutions, where a number of which are also optimal. The classical approach is to check them one by one, in an established order. But it cannot be guaranteed that the optima are uniformly distributed in the solution domain. Thus, a deterministic algorithm may not find you an optimum quickly enough. The advantage of a randomized algorithm is that there are actually no rules to set about the order in which the solutions are checked and for the cases when the optima are clustered together, it usually performs much better. See QueenInterference for a TopCoder example.

Randomized algorithms are particularly useful when faced with malicious attackers who deliberately try to feed a bad input to the algorithm. Such algorithms are widely used in cryptography, but it sometimes makes sense to also use them in TopCoder competitions. It may happen that you have an efficient algorithm, but there are a few degenerate cases for which its running time is significantly slower. Assuming the algorithm is correct, it has to run fast enough for all inputs. Otherwise, all the points you earned for submitting that particular problem are lost. This is why here, on TopCoder, we are interested in worst case execution time.

To challenge or not to challenge?
Another fierce coding contest is now over and you have 15 minutes to look for other coders' bugs. The random call in a competitor's submission is likely to draw your attention. This will most likely fall into one of two scenarios:

  1. the submission was just a desperate attempt and will most likely fail on many inputs.
  2. the algorithm was tested rather thoroughly and the probability to fail (or time out) is virtually null.

The first thing you have to do is to ensure it was not already unsuccessfully challenged (check the coder's history). If it wasn't, it may deserve a closer look. Otherwise, you should ensure that you understand what's going on before even considering a challenge. Also take into account other factors such as coder rating, coder submission accuracy, submission time, number of resubmissions or impact on your ranking.

Will "random" really work?
In most optimizing problems, the ratio between the number of optimal solutions and the total number of solutions is not so obvious. An easy, but not so clever solution, is to simply try generating different samples and see how the algorithm behaves. Running such a simulation is usually pretty quick and may also give you some extra clues in how to actually solve the problem.

C语言速成手册(三):数组、字符串、结构

Via http://www.matrix67.com/blog/archives/218 by Matrix67

目录:
C语言速成手册(一):基本数据类型、标准输出、函数
C语言速成手册(二):布尔值、条件判断、循环
C语言速成手册(三):数组、字符串、结构
C语言速成手册(四):指针、动态内存分配、标准输入
C语言速成手册(五):其它运算符、文件操作、其它函数
C语言速成手册(六):其它问题、后记

一维数组的定义、初始化和使用
    定义一个一维数组的格式如下:

    数组的下标范围总是从0开始(因此下标最大为数组大小减一)。下面一行语句定义了一个大小为10的长整型数组:

    这相当于下面的Pascal语句:


    C语言的数组范围左端点不能自定义,它的数组下标只能从0开始。

    下面几种方式可以在定义数组的同时进行初始化:

    上面两个语句是等价的。其中前一种方法依次对数组的前5个数进行初始赋值,后一种方法仅对数组的其中三个位置进行初始化。初始化中没有涉及到的下标所对应的数值自动被设为0。
    C语言允许数组的大小为一个变量,但这样的数组在定义时不能像上面一样进行初始化。
    这种初始化方法只在定义数组时用,不能用于程序中的赋值。数组之间也不能直接赋值,你不能把数组a整个赋值给数组b。

    程序中使用数组的方法和Pascal一样。下面的程序将输出1000以内的素数:


    当一维数组作为函数参数时,数组大小可以不写,以适应不同长度的数组。通常你还需要另一个参数告诉函数你的数组有多大。下面这个函数返回数组中的最大值:

    下面的代码合法地调用了上面的函数。
 

C语言中的字符串
    C语言也使用字符数组作为字符串。定义一个char a[20],就相当于定义了一个长度不超过20的字符串。Pascal中使用a[0]记录字符串的长度,字符串内容从a[1]开始;但C语言并不直接记录字符串长度,a[0]表示字符串的第一个字符,最后以ASCII码0(或写成字符'\0')标记字符串结尾。你可以直接将一个字符串赋给字符数组,也可以在printf中使用%s标识输出一个字符数组。记住,a[2]表示字符串中的第三个字符,因为C的数组下标是从0开始的。
    观察下列代码:

    程序的输出为:

    == 或 + 等运算符对字符串无效。

    下面的函数返回字符串的字符数:
 

    赋值时,如果字符串太长了,有两种方法可以让你分行写。一是在行末加一个反斜杠表示和下一行相连,二是每一行都用双引号注明(编译器会自动把它连接起来)。下面两个代码是等价的。注意第一个代码中的第二行必须顶格写,否则第二行前面的空格也要算进字符串里。
 

    和数组一样,对字符串的赋值只能在定义时使用,程序中不能这样做。

多维数组的定义、初始化和使用
    定义一个多维数组的格式如下:


    例如,下面这个语句定义了一个三维数组:

   同样地,每一维的大小都是从0开始算的。因此上面的语句相当于Pascal中的:
 

    多维数组的初始化和一维数组类似。例如,我们经常需要定义方向常量:


    这还可以直接写成:

    多维数组的初始化同样是未定义者自动填零,因此还可以写成:
 

    程序中使用多维数组时必须用多个方括号,即dir[2][1]不能写成dir[2,1]。

    当多维数组作为函数的参数时,只有第一维的大小可以不写。因此,下面的三个函数中前两个是合法的,第三个是不合法的。


    为了让参数仍然适用于各种大小的数组,C语言允许这样定义函数:


    例如,下面的函数递归地计算行列式:


    下面的代码片段正确地调用了上面的函数:
 

结构的定义、初始化和使用
    Pascal中的记录类型在C语言中叫做“结构”。定义一个结构的方式如下:

    注意花括号后面需要有一个分号。下面定义一个date结构:


    这样你就获得了一个名为struct date的类型名。和变量的定义一样,一个结构的定义只能供当前函数(的当前语句块)中后面的部分使用。因此通常把结构的定义放在所有函数的前面作为一个全局的定义。之后,你便可以写这样的语句:
 

    结构的使用方法同Pascal的记录类型一样。例如,下面的函数用于计算某一天是星期几(Zeller公式):
 

    给一个结构赋初始值和数组的初始化差不多。下面两个语句是等价的:


    这种方法也可以用于程序中的赋值操作,但需要加上一个类型转换(见这里的“名词动用”一节)。例如,下面三个代码片段都是等价的:


    下面的语句调用了zeller函数,输出自1583年来的每个13日都是星期几。和本文无关的问题:有人知道为什么我从1583年开始算么?
 

 

C语言速成手册(二):布尔值、条件判断、循环

Via http://www.matrix67.com/blog/archives/218 by Matrix67

目录:
C语言速成手册(一):基本数据类型、标准输出、函数
C语言速成手册(二):布尔值、条件判断、循环
C语言速成手册(三):数组、字符串、结构
C语言速成手册(四):指针、动态内存分配、标准输入
C语言速成手册(五):其它运算符、文件操作、其它函数
C语言速成手册(六):其它问题、后记

继续阅读

那些VisualStudio隐藏的调试功能

转载自 http://www.cnblogs.com/developersupport/p/visualstudio-debugging-tips.html via 微软互联网开发支持

VisualStudio是一个强大的调试工具,里面很多隐藏功能少有人问津,但是在特定场景可以节省你很多时间,本文主要介绍一些VisualStudio调试相关的隐藏功能。

运行到指针(Run to cursor)

大多数人用Visual Studio在调试程序的时候先在程序开始的时候设置一个断点,然后依次F10/F11到自己想要查看的逻辑。如果这个过程我们需要仔细查看每一步的变量或者执行路径,这样做无可厚非,但是如果我们不想关心前面执行的逻辑,我们可以使用Run to cursor功能,只需要鼠标指针点到你想要执行到的那一行代码,Ctrl+F10,程序直接停在了鼠标指针的那行代码。

继续阅读

OI青花瓷

via 百度noip吧

哥尼斯堡七桥边我们的连线
丽洁神犇嫩模间难存的情缘
当图灵机看见这也会被停机
NP解释不了的难题
搜索会爆无向图慢慢去遍历
只为能够找到你心底的记忆
神器SPFA
队列进出我们的足迹
线性规划难找我们的交集
算心底的梦忆靠容斥原理
二进制连篇幅代我说真爱你
Dev-C感动得去编译
平衡树轻旋转你我在隔壁
将你我连一起矩阵快速幂
看你我完美结合算法多美丽
你眼带笑意
数字三角行阵间递推难了解
斐波那契数列中恩怨何时结
二叉树上的禁果摘下归你我
藏进最长非降序列里
01背包装不下曾经的点滴
一切伤痕作浮云压进栈之底
红娘一般的匈牙利
联系我们不用并查集
心如凸包体积计算不容易
增广路来拓宽一定走进你
用剪枝剪去一切别人的记忆
得与失并不用去博弈
大脑里我找你匹配KMP
仿佛昨日重现AC自动机
二分图你我牵手一起的奇迹
感动着天地

发自 WordPress for Android