每天修一根,如果哪天發現這根是壞的就退出。求期望天數。
考場上想到了如果將修改弄成一個序列,退出就是滿足i<=pos[i],但卻沒有想到可以欽定前面的修改順序來計數,期望就是總貢獻除以排列數(n!)。
每個1都可能成爲退出的地方。對於第k個1,要滿足前k-1個1都是i>pos[i],對於第k個1,i<=pos[i],剩下的亂搞就行。
所以對於第k個1,這樣的排列數爲
最後別忘了如果一個1都沒觸犯,還是有n天/排列的貢獻。
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define int long long
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;ch=getchar();
}return cnt*f;
}
char ch[1000003];
int n,s[1000003];
int mul[1000003];
int pos[1000003],cnt;
int fac[1000003];
int ans;
const int mod=998244853;
int ksm(int a,int b){
int sum=1;
while(b){
if(b&1)sum=sum*a%mod;a=a*a%mod;b>>=1;
}return sum;
}
signed main(){
n=in;scanf("%s",ch+1);for(int i=1;i<=n;i++)s[i]=ch[i]-'0';
for(int i=1;i<=n;i++){
if(s[i]==1)pos[++cnt]=i,mul[cnt]=pos[cnt]-cnt;
}mul[0]=1;
for(int i=2;i<=cnt;i++)mul[i]=mul[i-1]*mul[i]%mod;
fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
// cout<<fac[0]<<" "<<pos[1]<<" "<<mul[1]<<endl;
// for(int i=1;i<=3;i++)cout<<fac[i]<<" ";cout<<endl;
// for(int i=1;i<=cnt;i++)cout<<pos[i]<<" ";cout<<endl;
// for(int i=1;i<=cnt;i++)cout<<mul[i]<<" ";cout<<endl;
for(int i=1;i<=cnt;i++){
ans=(ans+fac[n-i]*(n-pos[i]+1)%mod*mul[i-1]%mod*pos[i])%mod;
}//cout<<ans<<endl;
ans=(ans+mul[cnt]*fac[n-cnt]%mod*n%mod)%mod;
// cout<<ans<<endl;
cout<<ans*ksm(fac[n],mod-2)%mod;
return 0;
}