如上,赋值语句写错,应该是b[i][j]
题目链接
3744 -- Scout YYF I
期望dp+矩阵快速幂
q期望dp,分段讨论,矩阵快速幂
#include
#include
#include
#include
#include
using namespace std;
//矩阵赋值,a=b
void copy(double a[2][2], double b[2][2]) {
for(int i = 0;i < 2;i++)
for (int j = 0; j < 2; j++) {
a[i][j] = b[i][j];
}
}
//输入a和b;输出a*b的结果,存在res中
void mul(double a[2][2], double b[2][2], double res[2][2]) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
res[i][j] = 0;
for (int k = 0; k < 2; k++) {
res[i][j] += a[i][k] * b[k][j];
}
}
}
}
//计算a^length,结构存储在res中
//res=a^length
void exponent_( double res[2][2],double a[2][2],int length) {
res[0][0]=1.0,res[0][1]=0,res[1][0]=0,res[1][1]=1;//单位矩阵
double tmp[2][2], tmpa[2][2], tmpa1[2][2];
copy(tmp, res); copy(tmpa ,a);copy(tmpa1, a);//tmp用于存储res临时值,tmpa和tmpa1分别存储a和a*a的临时值
while (length) {
if (length & 1)mul(tmpa, res, tmp);//tmp=res*a;//res=tmp;
copy(res, tmp);
//update the tmpa
mul(tmpa, tmpa, tmpa1);
copy(tmpa, tmpa1);
length >>= 1;
}
}
int main()
{
int n; double p;
while (scanf("%d %lf", &n, &p) != EOF)
{
int x[30];
for (int i = 0; i < n; ++i) scanf("%d", &x[i]);
sort(x, x + n);//排序
double ans = 1.0;
double c[2][2];
c[0][0] = p, c[0][1] = 1.0 - p;
c[1][0] = 1.0, c[1][1] = 0.0;
double a[2][2] = { 1,0,0,1 };
exponent_(a, c, x[0] - 1);
ans *= (1 - a[0][0]);
for (int i = 1; i < n; ++i)
{
if (x[i] == x[i - 1]) continue;
exponent_(a, c, x[i] - x[i - 1] - 1);
ans *= (1.0 - a[0][0]);
}
printf("%.7f\n", ans);
}
return 0;
}
说明,使用数组指针传参时,注意是否修改指针存储的内容,如果不需要修改,则进行深复制,只取内容,不操作原地址存放的内容。
快速乘法
矩阵快速幂 | 幻悠尘的小窝
快速乘法算法原理及实现_langzi989的博客-CSDN博客_快速乘法
某个软件有s个子系统,会产生n种bug
某人一天发现一个bug,这个bug属于一个子系统,属于一个分类
每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n
问发现n种bug,每个子系统都发现bug的天数的期望。
dp[i][j]表示已经找到i种bug,j个系统的bug,达到目标状态的天数的期望
dp[n][s]=0;要求的答案是dp[0][0];
dp[i][j]可以转化成以下四种状态:
dp[i][j],发现一个bug属于已经有的i个分类和j个系统。概率为(i/n)*(j/s);
dp[i][j+1],发现一个bug属于已有的分类,不属于已有的系统.概率为 (i/n)*(1-j/s);
dp[i+1][j],发现一个bug属于已有的系统,不属于已有的分类,概率为 (1-i/n)*(j/s);
dp[i+1][j+1],发现一个bug不属于已有的系统,不属于已有的分类,概率为 (1-i/n)*(1-j/s);
#include
#include
#include
#include
#include
using namespace std;
double dp[1010][1010];
int main(){
int n,s;
while(scanf("%d%d",&n,&s)!=EOF){
dp[n][s]=0;
for(int i = n;i>=0;i--)
for (int j = s;j >= 0;j--){
if(i==n&&j==s)continue;
dp[i][j]=(i*(s-j)*dp[i][j+1]+(n-i)*j*dp[i+1][j]+(n-i)*(s-j)*dp[i+1][j+1]+n*s)/(n*s-i*j);
}
printf("%.4lf\n",dp[0][0]);
}
return 0;
}