題目在這裏呀~
這題讓我理解了很長一段時間(兩天誒),當然不是全天啦。
題意
有n盞燈初始有一個狀態,現隨機選一盞燈i,將i和它的約數的燈的狀態都改變。
噹噹前狀態採用最優方案還需要的步數小於等於k時,直接採用最優方案。問期望步數。
題解
先考慮用最優方案需要幾次,即從大到小枚舉,然後如果要改就改。(應該可以省略吧qaq
然後考慮概率DP,f[i]表示將有i盞燈亮着變爲i-1盞的期望。
有 n/i 的概率選到亮着的燈,則只需要1次。有1-n/i的概率選到沒亮的燈,那麼在之後的某一次操作中一定還會將燈在關掉,所以期望步數爲(1+f[i+1]+f[i])。
所以
邊界情況f[n]=1,f[i]=1(i=1~k)
//Suplex
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
#define N 100000+1000
using namespace std;
const int mod=100003;
int n,k,a[N],flag[N],s;
ll fac,ans,inv[N],f[N];
void pre()
{
fac=1;
for(int i=1;i<=n;i++) fac=fac*(ll)i % mod;
inv[1]=1;
for(int i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod % i] % mod;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
pre();
for(int i=n;i;i--){
int now=a[i];
for(int j=i+i;j<=n;j+=i) if(flag[j]) now^=1;
if(now) flag[i]=1,s++;
}
if(s<=k){printf("%lld\n",(ll)s*fac % mod);return 0;}
f[n]=1;
for(int i=1;i<=k;i++) f[i]=1;
for(int i=n-1;i>k;i--){
f[i]=(ll)(n-i)*(f[i+1]+1) % mod*inv[i] % mod+1;
f[i] %= mod;
}
for(int i=1;i<=s;i++) ans+=f[i],ans %= mod;
ans=ans * fac % mod;
printf("%lld\n",ans);
return 0;
}