1. 程式人生 > >[Shoi2017]分手是祝願

[Shoi2017]分手是祝願

vector log space using name ref col turn 最優

題鏈

我們可以從大到小搞一搞,那麽就有50分了。

然後我們可以證明,這個方案是最優方案腦殘選錯幾次再把選錯的幾次取消。

因為在每個點最多選一次的情況下解唯一。

那麽就可以對最優方案列DP,然後PaPaPa。

#include<bits/stdc++.h>
#define mo 100003
#define pb push_back
#define LL long long
using namespace std;
int n,k,a[mo];
LL inv[mo],f[mo],ans,anw;
vector<int> v[mo];
int  main () {
    freopen(
"trennen.in","r",stdin); freopen("trennen.out","w",stdout); scanf("%d %d",&n,&k); for (int i=1;i<=n;i++) scanf("%d",a+i); inv[1]=1; for (int i=2;i<mo;i++) inv[i]=(mo-mo/i)*inv[mo%i]%mo; for (int i=1;i<=n;i++) for (int j=i;j<=n;j+=i) v[j].pb(i);
for (int i=n;i;i--) if (a[i]){ for (int j=v[i].size()-1;~j;j--) a[v[i][j]]^=1; anw++; } if (anw<=k) { for (int i=1;i<=n;i++) (anw*=i)%=mo; printf("%d\n",anw); return 0;} f[n]=1;ans=k; for (int i=n-1;i>k;i--) f[i]=(1+inv[i]*(1+f[i+1])%mo*(n-i))%mo;
for (int i=max(k+1,2);i<=anw;i++) ans+=f[i]; ans%=mo; for (int i=1;i<=n;i++) (ans*=i)%=mo; printf("%lld\n",ans); return 0; }

[Shoi2017]分手是祝願