【CodeForces 261B】Maxim and Restaurant(DP,期望)

题目链接

第一种解法是$O(n^3*p)$的:
f[i][j][k]表示前i个人进j个人长度为k有几种方案(排列固定为123..n时)。
$f[i][j][k]=f[i-1][j][k]+f[i-1][j-1][k-a[i]]$
最外层枚举t表示被卡的那个人。i=t时不加上f[i-1][j-1][k-a[i]]。
$ans={{(\sum f[n][j][k]*j*j!*(n-1-j)!)+(\sum f[n][n][k]*n)}}/(n!)$。

可以看看这篇题解

#include<cstdio>
#include<cstring>
#define N 55
int n,p,a[N];
double f[N][N][N],ans,c[N]= {1};
int main(){
    scanf("%d",&n);
    for(int i=1; i<=n; i++){
        scanf("%d",&a[i]);
        c[i]=c[i-1]*i;
    }
    scanf("%d",&p);
    for(int t=0; t<=n; t++){
        memset(f,0,sizeof f);
        f[0][0][0]=1;
        for(int i=1; i<=n; i++)
            for(int j=0; j<=i; j++)
                for(int k=0; k<=p; k++){
                    f[i][j][k]=f[i-1][j][k];
                    if(j>=1&&t!=i&&k>=a[i])f[i][j][k]+=f[i-1][j-1][k-a[i]];
                }
        for(int j=1; j<n; j++)
            for(int k=1; k<=p; k++)if(a[t]+k>p)
                ans+=c[j]*c[n-1-j]/c[n]*f[n][j][k]*j;
        for(int k=1; k<=p; k++)ans+=f[n][n][k]*n;
    }
    printf("%lf",ans);
}

还可以更高效,$O(n^2*p)$
参考题解

f[i][j][k]表示前i个人至少进j个人这j个人的长度和为k有几种方案(排列为123..n时)。
那么$ans=(\sum f[n][j][k]*j!*(n-j)!/(n!)$。

我原来不太理解为什么至少j个人就是这么推,问了下队友,说是因为没有卡后面的,所以有可能可以进更多人。
其实第一种方法算的f也是至少j个人,然后在后面累加ans时再卡住第j+1个人。

并且可以用滚动数组优化为2维数组。

#include<cstdio>
#define N 51
int n,a[N],p;
double fac[N]= {1},f[N][N],tol,ans;
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",a+i);
        fac[i]=fac[i-1]*i;
        tol+=a[i];
    }
    scanf("%d",&p);
    if(tol<=p)
    {
        printf("%d",n);
        return 0;
    }
    f[0][0]=1;
    for(int i=1; i<=n; i++)
        for(int j=n-1; j>=0; j--)
            for(int k=0; k+a[i]<=p; k++)
                f[j+1][k+a[i]]+=f[j][k];
    for(int j=1; j<=n; j++)
        for(int k=0; k<=p; k++)
            ans+=f[j][k]*fac[j]*fac[n-j];
    ans/=fac[n];
    printf("%lf",ans);
}

  

时间: 2024-10-13 14:37:06

【CodeForces 261B】Maxim and Restaurant(DP,期望)的相关文章

codeforces 261B Maxim and Restaurant(概率DP)

B. Maxim and Restaurant time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Maxim has opened his own restaurant! The restaurant has got a huge table, the table's length is p meters. Maxim has

Codeforces 123E Maze(树形DP+期望)

[题目链接] http://codeforces.com/problemset/problem/123/E [题目大意] 给出一棵,给出从每个点出发的概率和以每个点为终点的概率,求出每次按照dfs序从起点到达终点的期望. [题解] 首先对于期望计算有X(x,y)=X(x)*X(y),所以对于每次dfs寻路只要求出其起点到终点的期望步数,乘上起点的概率和终点的概率即可.对于一个固定起点和终点的dfs寻路,我们可以发现如果一个点在必要路径上,那么这条路被走过的期望一定为1,如果不在必要路线上,那么走

cf 261B.Maxim and Restaurant

什么什么期望的,不会! (题解http://blog.sina.com.cn/s/blog_140e100580102wj4e.html(看不懂)) #include<bits/stdc++.h> #define LL long long #define LD long double #define N 100005 using namespace std; inline int ra() { int x=0,f=1; char ch=getchar(); while (ch<'0' |

CF261B Maxim and Restaurant

我的blog 题目链接:CF261B Maxim and Restaurant \[preface\] 背包DP+期望的一道题 \[description\] 题目翻译有QwQ \[solution\] 我们要分两种情况讨论: \[\sum_{i=1}^{n}a[i]\leq p\] \[\sum_{i=1}^{n}a[i]> p\] 对于情况\(1\),显然就是n个人都可以坐,那么直接输出\(n\)即可. 对于请款\(2\), 设\(f(i,j,k)\)表示表示已经处理完前i个人选了j个人占了

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

CodeForces 30C Shooting Gallery 简单dp

题目链接:点击打开链接 给定n个气球 下面n行 x y t val 表示气球出现的坐标(x,y) 出现的时刻t,气球的价值val 枪每秒移动1个单位的距离 问: 射击的最大价值,开始时枪瞄准的位置任意. 思路: dp一下.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

CodeForces 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

Codeforces Round #259(div2)C(数学期望)

数学题. 关键是求最大值为k时有多少种情况,结果是kn-(k-1)n-1.可以这么想:每一次都从1至k里选,共kn种,这里需要再减去每一次都从1至k-1里面选的情况.当然也可以分类计数法:按出现几次k来分类,然后逆着用一下二项式定理得出结论. 整个的期望是Σk(kn-(k-1)n-1)/mn,其中k=1......n. 这里的技巧在于:由于n<=105,   kn显然会RE,那么就先把分母除上,每次算一个小于1的浮点数的n次方,肯定不会RE.C++中乘方用pow函数算是很快的. #include