期望动规一般有两种实现方式,一种是f[i]表示还剩i步到目标状态,求得的期望值,另一种是f[i]表示从还剩i步到还剩i-1步的期望增量。

这道题用的是后者,注意i步的状态有时会因为误操作而转移到i+1步的状态,这个需要考虑清楚。

对于每个状态,最优开关方式是固定的,就是每次将最大的亮的灯按灭。剩下的就是期望DP了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=100100,mod=100003;
int n,k,num,v[N];
ll t,b[N]; ll ksm(ll a,ll b){
ll res;
for (res=1; b; a=(a*a)%mod,b>>=1)
if (b & 1) res=(res*a)%mod;
return res;
} int main(){
freopen("bzoj4872.in","r",stdin);
freopen("bzoj4872.out","w",stdout);
scanf("%d%d",&n,&k);
rep(i,1,n) scanf("%d",&v[i]);
for (int i=n; i>=1; i--)
if (v[i]){
for (int j=1; j*j<=i; j++)
if (i%j==0){
v[j]^=1;
if (j*j!=i) v[i/j]^=1;
}
num++;
}
for (int i=n; i; i--) b[i]=(b[i+1]*(n-i)%mod+n)%mod*ksm(i,mod-2)%mod;
if (n==k || k>num) t=num;
else{
for (int i=num; i>k; i--) t=(t+b[i])%mod;
t=(t+k)%mod;
}
rep(i,1,n) t=t*i%mod;
printf("%lld\n",t);
return 0;
}
04-26 17:45
查看更多