zoukankan      html  css  js  c++  java
  • [CSPS模拟测试]:B(期望DP) HEOI

    题目传送门(内部题151)


    输入格式

      第一行一个整数$N$。
      第二行$N$个整数,第$i$个为$a_i$。


    输出格式

      一行一个整数,表示答案。为避免精度误差,答案对$323232323$取模。
      即设答案化为最简分式后的形式为$\frac{a}{b}$,其中$a$和$b$互质。输出整数$x$使得$bx\equiv a(\mod 323232323)$且$0\leqslant x<323232323$。可以证明这样的整数$x$是唯一的。


    样例

    样例输入:

    3
    2 3 3

    样例输出:

    202020207


    数据范围与提示

      每个测试点$10$分,共$10$个测试点:

      对于所有的数据,有:$1\leqslant N,a_i$。


    题解

    考虑$DP$,设$f_i$表示$a_i$被选的期望次数,注意这里是$a_i$。

    那么答案就是:

    $$ans=\sum\limits_{i=2}^nf_{a_i}}+a_1$$

    想办法求出$f_i$。

    考虑从$N\leqslant 2$入手,相当于是从$(a_1,a_i)$走到坐标轴的期望次数,每次都有$\frac{1}{2}$的概率走不同的方向;类比这种做法,可以列出$a_i$的贡献式子:

    $$\sum\limits_{i=0}^{a_i-1}i\times \frac{C_{a_1-1+i}^i}{2^{a_1+i}}+a_i\times (1-\sum\limits_{i=0}^{a_i-1}\frac{C_{a_1-1+i}^i}{2^{a_1+i}}$$

    看似还是$\Theta(N^2)$的,但是实际上我们可以线性递推出来$f[i]$,然后直接统计答案就好了。

    时间复杂度:$\Theta(\max(a_i))$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=323232323;
    const int in2=161616162;
    int N;
    int a[500001];
    long long fac[500001],inv[500001];
    long long f[500001],w,p,inc,res;
    long long ans;
    long long qpow(long long x,long long y)
    {
    	long long res=1;
    	while(y)
    	{
    		if(y&1)res=res*x%mod;
    		x=x*x%mod;y>>=1;
    	}
    	return res;
    }
    void pre_work()
    {
    	fac[0]=1;
    	for(int i=1;i<=500000;i++)fac[i]=fac[i-1]*i%mod;
    	inv[500000]=qpow(fac[500000],mod-2);
    	for(int i=500000;i;i--)inv[i-1]=inv[i]*i%mod;
    }
    long long C(int x,int y){return fac[x]*inv[y]%mod*inv[x-y]%mod;}
    int main()
    {
    	pre_work();
    	scanf("%d",&N);
    	for(int i=1;i<=N;i++)
    		scanf("%d",&a[i]);
    	inc=p=qpow(qpow(2,a[1]),mod-2);
    	for(int i=1;i<=500000;i++)
    	{
    		inc=inc*in2%mod;
    		f[i]=(w+i*(1-p)+mod)%mod;
    		res=C(a[1]-1+i,i)*inc%mod;
    		p=(p+res)%mod;w=(w+res*i)%mod;
    	}
    	ans=a[1];
    	for(int i=2;i<=N;i++)ans=(ans+f[a[i]]+mod)%mod;
    	printf("%lld",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    linux内核的配置
    数据库常用SQL语句(二):多表连接查询
    数据库常用SQL语句(三):子查询
    数据库常用SQL语句(一):常用的数据库、表操作及单表查询语句
    数据库管理系统软件的软件架构
    Java对象的序列化
    关于重写对象equals方法的问题
    对Spring的理解
    Myeclipse项目工程目录中各种Libraries的含义
    对JDBC的使用理解
  • 原文地址:https://www.cnblogs.com/My-tiantian/p/11855125.html
Copyright © 2011-2022 走看看