【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; }