2991: [2012北大校赛]Do Not Gamble
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 8 Solved: 3
[ Submit][ Status][ Discuss]
Description
Have you ever gambled? I wish you not. Being a professional gambler for three years, I learned every
trick they play. Gambling is has nothing to do with luck. It is all about cheating.One of the most
elementary tricks is "mercury dice". Instead of being solid, there is a hollow chamber, filled with
mercury, inside of the dice. This little modification makes the dice asymmetric, so that, the probab
ility of each outcome is not equal. Imprecisely, which face is up, depends on the previous state.To
simplify the model, we use "mercury coin" here. As we mentioned, the state (head or tail) after toss
ing depends on the state before. The probability of that the two states are same, is p. For example,
if the head side is up now, the probability that, the coin is still head up after tossing is p. And
the probability that the tail side come up is 1-p. If p=0.5, it is a common coin. When p≠ 0.5, thi
s coin is mercury coin. Assume the coin is head up now. After we toss Ntimes, what is the probabilit
y that, the number of heads is less than a certain number K?
Input
The test file contains multiple lines, and each line is a test case.
Each test cases consists of three numbers
N K p
N and K are integers, and p is a float number.
N ≤ 30000
K ≤ N
0 ≤ p ≤ 1
Output
For each test case, output the probability that, after tossing N times, the number of heads is less
than K. Rounded to the three digit after the decimal point.
Sample Input
171 88 0.107
Sample Output
0.83785
HINT
Source
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 2E5 + 10;
typedef double DB;
const DB PI = acos(-1.0);
struct Virt{
DB r,i;
Virt(){}
Virt(DB r,DB i): r(r),i(i){}
Virt operator + (const Virt &b) {return Virt(r + b.r,i + b.i);}
Virt operator - (const Virt &b) {return Virt(r - b.r,i - b.i);}
Virt operator * (const Virt &b) {return Virt(r*b.r - i*b.i,r*b.i + i*b.r);}
Virt operator * (const DB &t) {return Virt(r*t,i*t);}
Virt operator / (const DB &t) {return Virt(r/t,i/t);}
}F[maxn],G[maxn],Fr[maxn],Gr[maxn],A[maxn],B[maxn],C[maxn],D[maxn];
int n,m;
DB p,q;
bool flag;
void Rader(Virt *a,int len)
{
int j = len >> 1;
for (int i = 1; i < len - 1; i++) {
if (i < j) swap(a[i],a[j]);
int k = len >> 1;
while (j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
}
void FFT(Virt *a,int len,int on)
{
Rader(a,len);
DB T = 2.00*PI*(DB)(on);
for (int k = 2; k <= len; k <<= 1) {
Virt wn = Virt(cos(T/(DB)(k)),sin(T/(DB)(k)));
for (int i = 0; i < len; i += k) {
Virt w = Virt(1.00,0.00);
for (int j = i; j < i + (k>>1); j++) {
Virt u = a[j];
Virt t = w*a[j + (k>>1)];
a[j] = u + t;
a[j + (k>>1)] = u - t;
w = w*wn;
}
}
}
if (on == -1)
for (int i = 0; i < len; i++)
a[i] = a[i]/(DB)(len);
}
void Multi(int len)
{
if (!flag) {
for (int i = 0; i <= len; i++)
A[i] = F[i],B[i] = G[i];
flag = 1;
return;
}
int N = len << 2;
FFT(A,N,1); FFT(B,N,1);
FFT(F,N,1); FFT(G,N,1);
FFT(Fr,N,1); FFT(Gr,N,1);
for (int i = 0; i < N; i++) {
Virt a = A[i],b = B[i];
A[i] = a*F[i] + b*Gr[i];
B[i] = a*G[i] + b*Fr[i];
}
FFT(A,N,-1); FFT(B,N,-1);
FFT(F,N,-1); FFT(G,N,-1);
FFT(Fr,N,-1); FFT(Gr,N,-1);
}
void Solve(int y)
{
F[1] = Fr[0] = Virt(p,0.00);
G[0] = Gr[1] = Virt(q,0.00);
int N = 1;
for (; y; y >>= 1) {
if (y & 1) Multi(N);
int Now = N << 2;
FFT(F,Now,1); FFT(Fr,Now,1);
FFT(G,Now,1); FFT(Gr,Now,1);
for (int i = 0; i < Now; i++) {
C[i] = F[i]*F[i] + G[i]*Gr[i];
D[i] = F[i]*G[i] + G[i]*Fr[i];
}
FFT(C,Now,-1); FFT(D,Now,-1);
N <<= 1;
for (int i = 0; i <= N; i++) {
Fr[N - i] = F[i] = C[i];
Gr[N - i] = G[i] = D[i];
}
for (int i = N + 1; i < Now; i++) {
F[i] = Fr[i] = Virt(0.00,0.00);
G[i] = Gr[i] = Virt(0.00,0.00);
}
}
}
void Clear(int len)
{
int N = len << 2;
for (int i = 0; i < N; i++) {
F[i] = Fr[i] = G[i] = Gr[i] = Virt(0.00,0.00);
A[i] = B[i] = C[i] = D[i] = Virt(0.00,0.00);
}
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
while (scanf("%d%d%lf",&n,&m,&p) != EOF) {
q = 1.00 - p;
Solve(n);
DB ans = 0;
flag = 0;
for (int i = 0; i < m; i++)
ans += A[i].r + B[i].r;
if (fabs(ans) < 1e-6) puts("0.00000");
else printf("%.5f\n",ans);
Clear(n);
}
return 0;
}