问题描述:
生成n个∈[a,b]的随机整数,输出它们的和为x的概率。
输入格式
一行输入四个整数依次为n,a,b,x,用空格分隔。
输出格式
输出一行包含一个小数位和为x的概率,小数点后保留四位小数
样例输入
2 1 3 4
样例输出
0.3333
数据规模和约定
对于50%的数据,n≤5.
对于100%的数据,n≤100,b≤100.
分析:
一看到题目,由于是蓝桥杯的而不是ACM的,数据都不是很大。所以我的第一感觉就是暴力遍历n次。但是由于n是一个不定的数,所以就只能再想一想了。
用动态规划法,将n次产生值看成n种状态,d[i][j]表示第i次产生值后的和为j的概率,又因为第i次的和j>=i*a && j<=i*b,又d[i][j]的产生根据d[i-1][]的情况有多种情况,例如:如果d[i-1][j-a],那么d[i][j]=d[i-1][j-a]*p(即前i-1次的和为j-a,第i次取的是a),只需要将所有可能加起来就好。
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
double p[110][10010];
void dp(int n,int a,int b,int x);
int main()
{
int n,x,a,b;
cin>>n>>a>>b>>x;
memset(p,0,sizeof(p));
dp(n,a,b,x);
printf("%0.4lf",p[n][x]);
return 0;
}
void dp(int n,int a,int b,int x)
{
double pl=1.0/(b-a+1);
double pp=0.0;
int i,j,k;
for(i=1;i<=n;i++)
{
for(j=a*i;j<=b*i;j++)
{
if(i==1)
{
p[i][j]=pl;
}
else
{
pp=0.0;
for(k=a;k<=b;k++)
{
if(j>=k)
{
pp+=p[i-1][j-k]*pl;
}
}
p[i][j]=pp;
}
}
}
}