分析
首先判断必须得按的键的个数,这个倒序枚举亮着的灯,然后设 d p [ i ] dp[i] dp[i]表示有 i i i个正确选择并选择正确的期望操作次数,那么 d p [ i ] = i n + n − i n ( d p [ i ] + d p [ i + 1 ] + 1 ) + 1 , d p [ n + 1 ] = 0 dp[i]=\frac{i}{n}+\frac{n-i}{n}(dp[i]+dp[i+1]+1)+1,dp[n+1]=0 dp[i]=ni+nn−i(dp[i]+dp[i+1]+1)+1,dp[n+1]=0,若必须得按的键在 k k k以内就不需要随机了,否则答案就是 k + ∑ i = k + 1 c n t d p [ i ] k+\sum_{i=k+1}^{cnt}dp[i] k+∑i=k+1cntdp[i]
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#define rr register
using namespace std;
typedef long long ll;
const int mod=100003;
bool a[mod]; int n,k,cnt;
ll dp[mod],inv[mod];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
n=iut(); k=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=n;i;--i)
if (a[i]){
++cnt; rr int t=sqrt(i);
for (rr int j=1;j<=t;++j)
if (i%j==0){
a[j]^=1;
if (j*j!=i) a[i/j]^=1;
}
}
dp[n+1]=0; inv[1]=1;
for (rr int i=2;i<=n;++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (rr int i=n;i;--i)
dp[i]=((n-i)*dp[i+1]+n)*inv[i]%mod;
rr ll ans=cnt;
if (cnt>k){
ans=k;
for (rr int i=cnt;i>k;--i) ans=(ans+dp[i])%mod;
}
for (rr int i=1;i<=n;++i) ans=ans*i%mod;
return !printf("%lld",ans);
}