六省联考2017 分手是祝愿
略有订正,求管理员通过。
不知道什么时候过的题,今天看到有同学在做,觉得有必要写一写题解。
题目
题意:有一个长度为
容易证明,一种最优的操作策略是每次操作最右边的为
设
则
暴力高斯消元复杂度爆炸。
设
代入得
整理得到
边界条件
做完了。
以下代码时间复杂度为
#include<cstdio>
const int N=1e5+1,M=1e5+3;
int n,m,c,a[N],inv[M],f[N],b[N];
inline int F(int n){return n?1ll*F(n-1)*n%M:1;}
int main(){
int t;
inv[1]=1;
for(int i=2;i<M;i++)inv[i]=1ll*inv[M%i]*(M-M/i)%M;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",a+i);
for(int i=n,j;i;i--)if(a[i]){
for(j=1;j*j<i;j++)
if(i%j==0)a[j]^=1,a[i/j]^=1;
if(j*j==i)a[j]^=1;
c++;
}
if(m==n||m==n-1)return 0*printf("%lld",1ll*F(n)*c%M);
for(int i=0;i<=m;i++)f[i]=i;
b[n]=1;
for(int i=n-1;i>m;i--)
b[i]=(1ll*(n-i)*b[i+1]+n)%M*inv[i]%M;
for(int i=m+1;i<=n;i++)f[i]=(f[i-1]+b[i])%M;
return 0*printf("%lld",1ll*F(n)*f[c]%M);
}