【Luogu】P3750分手是祝愿(期望DP)

  题目链接

  这题好喵啊……

  设f[i]是最少用i次才能全关上转移到最少用i-1次才能全关上灯的期望值,那么n个灯里有i个是正确的,剩下的都是不正确的

  因此期望是$f[i]=frac{n}{i}+frac{(n-i)*f[i+1]}{i}$

  然后我们把初始状态最少用多少次才能关掉求出来

  DP一遍,最后统计答案。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define maxn 100020
#define mod 100003
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

vector<long long>s[maxn];

long long inv[maxn];
long long q[maxn];
long long f[maxn];

int main(){
    long long n=read(),m=read();
    inv[1]=1;
    for(long long i=2;i<=n;++i)    inv[i]=(-mod/i*inv[mod%i]%mod+mod)%mod;
    for(long long i=1;i<=n;++i)    q[i]=read();
    for(long long i=1;i<=n;++i)
        for(long long j=i;j<=n;j+=i)    s[j].push_back(i);
    long long last=0;
    for(long long i=n;i>=1;--i){
        if(q[i]==0)    continue;
        for(long long j=0;j<s[i].size();++j)    q[s[i][j]]^=1;
        last++;
    }
    f[n]=1;
    for(long long i=n-1;i>m;--i)    f[i]=(n*inv[i]%mod+((n-i)*f[i+1]%mod)*inv[i]%mod)%mod;
    for(long long i=1;i<=m;++i)    f[i]=1;
    long long ans=0;
    for(long long i=1;i<=last;++i)    ans=(ans+f[i])%mod;
    for(long long i=1;i<=n;++i)    ans=(ans*i)%mod;
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-04-18 08:48  Konoset  阅读(128)  评论(0编辑  收藏  举报