ε=(´ο`*)))唉,我什么时候才能找到女票啊。
这个题实际对于考生很友好。
考试可以利用暴力推出正解。
对于5成数据:k==n
那么很明显倒着关灯是唯一最优解。
此时那些约数要选是一个集合。
那么如何处理这个集合?
定义f(i)表示这个集合内还有i个没选
f(i)成立的期望是:f(i-1)=(i)/(n)+(n-i)/(n)*(f(i+1))
转换一下:
0=i*(f(i)-f(i-1))+(n-i)*(f(i)-f(i+1))-n
易得:令g(i)=f(i)-f(i-1)
所以这是对f差分
而g(n)==1
为什么?
如果选了n个那么无论怎么选,这个集合都会变优,所以期望是1的
然后还考查了线性筛逆元。。。
#include<bits/stdc++.h>
using namespace std;
typedef int INT;
#define int long long
const INT N=4e5+100;
const int mod=1e5+3;
int g[N]={0};//f[i]-f[i-1]
int f[N]={0};
int fac[N]={0};
int inv[N]={0};
int a[N]={0};
int quick_pow(int x,int k){
int ret=1;
while(k){
if(k%2==1){
ret=(ret*x)%mod;
}
k/=2;
x=x*x%mod;
}
return ret;
}
int n,k;
int vis[N]={0};
void solve(){
int t=0;
for(int i=n;i>=1;i--){
int p=a[i];
for(int j=i*2;j<=n;j+=i){
if(vis[j]){
p^=1;
}
}
if(p)
vis[i]=1,t++;
}
if(t<=k){
cout<<t*fac[n]%mod<<endl;
return;
}
g[n]=1;
for(int i=1;i<=k;i++){
g[i]=1;
}
for(int i=n-1;i>k;i--){
g[i]=(n+(n-i)*g[i+1]%mod)*inv[i]%mod;
}
int ans=0;
for(int i=1;i<=t;i++){
ans+=g[i];
ans%=mod;
}
cout<<ans*fac[n]%mod;
}
INT main(){
scanf("%lld%lld",&n,&k);
fac[0]=1;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
fac[i]=fac[i-1]*i%mod;
}
inv[1]=1;
int P=mod;
for(int i=2;i<=n;i++){
inv[i]=(P-P/i)*inv[P%i]%P;
}
solve();
}