uva11021
题意:
给你K个毛球,每个毛球只能生存一天,但是每个毛球都有pi的概率繁殖i个毛球,问第 m 天后所有毛球死亡的概率。(所有毛球独立存在,互不影响)
思路:
概率dp
因为k只毛球都是相互独立的,我们只需要算出每个毛球m天死亡后的概率dp[m],然后答案就是 dp[m]k 。
设dp[i]表示所有毛球第i天后全部死亡的概率.
那么有
dp[i]=p0+p1∗dp[i−1]1+p2∗dp[i−1]2....pj∗dp[i−1]j
其中 pj 表示繁殖j个毛球的概率.
每只毛球到要在i-1天死亡,一共有几个毛球,所以为 dp[i−1]j
#include
#include
#include
using namespace std;
const int maxn = 1e3+5;
double p[maxn],dp[maxn];
int n,m,k;
int main()
{
int _,ca = 1;
cin>>_;
while(_--)
{
scanf("%d %d %d",&n,&k,&m);
for(int i = 0;i < n;++i)
scanf("%lf",&p[i]);
for(int i = 1;i <= m;++i)
{
dp[i] = 0;
for(int j = 0;j < n;++j)
dp[i] += p[j]*pow(dp[i-1],j);
}
double ans = pow(dp[m],k);
if(m == 0) ans = 0.0;
printf("Case #%d: %.7f\n",ca++,ans);
}
return 0;
}
uva11722
题意:
你和朋友都要乘坐火车,并且都会途径A城市。你们很想会面,但是你们到达这个城市的准确时刻都无法确定。你会在时间区间[t1,t2]中的任意时刻以相同的概率密度到达。你的朋友则会在时间区间[s1,s2]的任意时刻以相同的概率密度到达。你们的火车都会在A城市停留w分钟。只有你们所在的火车都停在A城市的时候,才可能会面。你的任务是计算出现这种情况的概率。
思路:
几何概型.
我已经忘了我高中学的所有知识….
一般可能性无穷的,或者一段区间,一个区域啊让你求概率啊 都可以想想几何概型.
设x轴为 t,y轴为s.则 (t1,t2)和(s1,s2)围出的矩阵为整个可能的全集。
因为两人要相遇即差为w,所以在画两条直线 s = t - w 和s = t + w.那么所有可行解即为两条直线之间和矩阵共同围成的面积.
阴影部分面积/矩阵面积 即为概率。
两个直线和矩阵有很多画法,计算时需要分类讨论
#include
using namespace std;
int t1,t2,s1,s2,w;
int ww,hh;
double solve(int w)
{
int ly,ry,ux,dx;
ly = t1 + w;
ry = t2 + w;
if(ly >= s2 )
return 0.0;
if(ry <= s1)
return ww*hh;
ux = s2 - w;
dx = s1 - w;
if(ly >= s1 && ly <= s2 && ux >= t1 && ux <= t2) return (ux - t1)*(s2 - ly)*0.5;
if(ry >= s1 && ry <= s2 && dx >= t1 && dx <= t2) return (ww*hh - (t2 - dx)*(ry - s1)*0.5);
if(dx >= t1 && dx <= t2 && ux >= t1 && ux <= t2) return (s2 - s1)*(ux - t1 + dx - t1)*0.5;
if(ly >= s1 && ly <= s2 && ry >= s1 && ry <= s2) return (t2 - t1)*(s2 - ly + s2 - ry)*0.5;
}
int main()
{
int _,ca = 1;
cin>>_;
while(_--)
{
scanf("%d %d %d %d %d",&t1,&t2,&s1,&s2,&w);
ww = t2 - t1;
hh = s2 - s1;
double ans1 = solve(w);
double ans2 = solve(-w);
//printf("%f %f",ans1,ans2);
printf("Case #%d: %.8f\n",ca++,(ans2-ans1)/(ww*hh));
}
return 0;
}
uva 11762
题意:
给你一个整数N,每次都可以在不超过N的素数中随机选择一个P,如果P是N的约数,则把N变成N/P,否则N不变,问平均情况下要多少次随机选择,才能把N变成1
思路:
期望dp.
考虑dp[n]表示整数N变为1需要的期望次数.
那么有:
dp[i]=1+dp[i]∗(1−g(i)p(i))+∑k|idp[i/k]∗1g(i)
其中g(i)为不超过i的素数中约数的个数
p(i)为不超过i的素数的个数.
整理一下得:
dp[i]=∑k|idp[i/k]+p(i)g(i)
由于i/ k < i 所以这个过程可以记忆化搜索一下.
#include
using namespace std;
const int maxn = 1e6+5;
typedef long long ll;
int n;
double dp[maxn];
int prime[maxn],cnt;
bool vis[maxn];
void init()
{
cnt = 0;
for(int i = 2;i < maxn;++i)
{
if(!vis[i])
prime[cnt++] = i;
for(int j = 0;j < cnt && (ll)prime[j]*i < maxn;++j)
{
vis[i*prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
return ;
}
double dfs(int x)
{
if(dp[x] != -1) return dp[x];
double ans = 0;
int g = 0,p = 0;
for(int i = 0;i < cnt && prime[i] <= x;++i)
{
p++;
if(x % prime[i] == 0)
{
g++;
ans += dfs(x / prime[i]);
}
}
ans = (ans + p)*1.0 / g;
return dp[x] = ans;
}
int main()
{
int _,ca = 1;
for(int i = 0;i < maxn;++i) dp[i] = -1.0;
dp[1] = 0;
init();
cin>>_;
while(_--)
{
scanf("%d",&n);
dfs(n);
printf("Case %d: %.10f\n",ca++,dp[n]);
}
return 0;
}