zoukankan      html  css  js  c++  java
  • [CSP校内集训]kat(期望DP)

    题意

    一本有n道题的练习册,katarina大佬每天都会做k道题。
    第一天做第1k题,第二天做第2k+1题……第n-k+1天做第n−k+1~n道题。
    每道题有它的难度值,假设今天katarina大佬做的题目中最大难度为t,那么今天katarina大佬的劳累度就是(w_t),做完这本书的劳累值就是每天的劳累值之和。
    题目的难度在1~m随机,求做完整本书的期望劳累值

    (n,m leq 500 , mod = 10^9+7)

    思路

    由于前面两道题都有点迷所以还以为这道题也是道神题

    性质:求每种排列的贡献和 等价于 一个滑动窗口的贡献( imes) ((n-k+1))

    性感)证明

    根据题意有:$$ans = sum_{i=1}{mn}{ (frac{1}{m^n} imes (a_1^i + a_2^i + ....... + a_{n-k+1}^i)) }$$其中(a_j^i)表示在第(i)种排列下第(j)个滑动窗口的贡献

    显然这个东西可以用乘法分配律按照(j)分开:$$ans = sum_{j=1}{n-k+1}{(frac{1}{mn} imes (a_j^1 + a_j^2 + ....... + a_j{mn}))}$$

    对于一个滑动窗口,在它范围外的其他格子不管怎么变都不会影响它的贡献,所以这样的(a)是相同的,每种贡献有(m^{n-k})

    把相同贡献的变成一个,最后变成:$$ans = sum_{j=1}^{n-k+1}{ (frac{1}{m^k} imes (a_j^1 + a_j^2 + ........ + a_j{m{n-k}}))) }$$

    发现此时答案为每个滑动窗口单独的贡献加起来,而每个滑动窗口的贡献又相同,所以就等于单个贡献( imes) ((n-k+1))

    对单个滑窗期望DP即可,这个复杂度可以是(O(mlogn))或者(O(nm)),比较基础就不写了(不能理解题解(O(n^2m))的睿智做法

    本题难点不在期望DP而在简化问题(当然像题解一样直接莽就另当别论了),其实(m)可以开到(10^5)

    Code

    #include<bits/stdc++.h>
    #define N 505
    #define Min(x,y) ((x)<(y)?(x):(y))
    #define Max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    typedef long long ll;
    const ll mod = 1000000007;
    int n,m,k;
    ll a[N],f[N][N],sum[N][N];
    
    template <class T>
    void read(T &x)
    {
    	char c; int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
    }
    ll quickpow(ll a,ll b)
    {
    	ll ret=1;
    	while(b)
    	{
    		if(b&1) ret=ret*a%mod;
    		a=a*a%mod;
    		b>>=1;
    	}
    	return ret;
    }
    
    int main()
    {
    	freopen("kat.in","r",stdin);
    	freopen("kat.out","w",stdout);
    	read(n);read(m);read(k);
    	for(int i=1;i<=m;++i) read(a[i]);
    	for(int i=1;i<=m;++i) f[1][i]=quickpow(m,mod-2),sum[1][i]=(sum[1][i-1]+f[1][i])%mod;
    	for(int i=2;i<=k;++i)
    	{
    		for(int j=1;j<=m;++j)
    		{
    			f[i][j]=(sum[i-1][j-1]+f[i-1][j]*j%mod)*quickpow(m,mod-2)%mod;
    			sum[i][j]=(sum[i][j-1]+f[i][j])%mod;
    		}
    	}
    	ll ans=0;
    	for(int i=1;i<=m;++i) ans=(ans + f[k][i]*a[i]%mod)%mod;
    	cout<<(ans*(n-k+1)%mod+mod)%mod<<endl;
    	return 0;
    }
    
  • 相关阅读:
    20200209 ZooKeeper 3. Zookeeper内部原理
    20200209 ZooKeeper 2. Zookeeper本地模式安装
    20200209 Zookeeper 1. Zookeeper入门
    20200206 尚硅谷Docker【归档】
    20200206 Docker 8. 本地镜像发布到阿里云
    20200206 Docker 7. Docker常用安装
    20200206 Docker 6. DockerFile解析
    20200206 Docker 5. Docker容器数据卷
    20200206 Docker 4. Docker 镜像
    Combining STDP and Reward-Modulated STDP in Deep Convolutional Spiking Neural Networks for Digit Recognition
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11762707.html
Copyright © 2011-2022 走看看