BZOJ 4827 [Shoi2017]分手是祝愿 ——期望DP

显然,考虑当前状态最少需要几步,直接贪心即可。

显然我们只需要考虑消掉这几个就好了。

然后发现,关系式找出来很简单,是$f(i) f(i+1) f(i-1)$之间的。

但是计算的时候并不好算。

所以把意义进行差分用$g(i)$表示从$i$到$i-1$期望的次数。

然后就找到了二阶递推式递推即可。

#include <map>
#include <ctime>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define md 100003
#define ll long long
#define maxn 100005
 
int n,k,a[maxn],g[maxn],cnt,fac,inv[maxn];
 
int main()
{
    scanf("%d%d",&n,&k);
    fac=1;F(i,2,n)fac=(ll)fac*i%md;
    F(i,1,n) scanf("%d",&a[i]);
    D(i,n,1)
    {
        if (a[i])
        {
            ++cnt;
            F(j,1,sqrt(i))
                if (i%j==0)
                {
                    a[i/j]^=1;
                    if (i/j!=j) a[j]^=1;
                }
        }
    }
    if (cnt<=k) {printf("%d\n",(ll)cnt*fac%md);return 0;}
    F(i,1,k) g[i]=1; g[n]=1;
    inv[1]=1;F(i,2,n) inv[i]=(ll)(md-md/i)*inv[md%i]%md;
    D(i,n-1,k+1) g[i]=((ll)(n-i)*g[i+1]%md+n)*inv[i]%md;
    int ans=0;
    F(i,1,cnt) ans+=g[i],ans%=md;
    printf("%d\n",(ll)ans*fac%md);
}

  

posted @ 2017-05-05 16:08  SfailSth  阅读(290)  评论(0编辑  收藏  举报