解题:2017六省联考 分手是祝愿
Posted ydnhaha
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题:2017六省联考 分手是祝愿相关的知识,希望对你有一定的参考价值。
首先考虑什么是最优策略,其实这个最优策略就是从大到小一个个按。因为小的不会也不能影响大的,显然这样按是最优且必须的,于是我们枚举下因数拿vector存一下,然后直接模拟就可以搞到$50pts$了(好像因为毕姥爷的数据造水了(?)导致这么做有80pts(雾 )
那么考虑在达到$k$前的这个随机按的过程,设$exp[i]$(代码里不要这么写,exp是cmath里的一个函数)表示还需要按对$i$次时的期望,那么有
$exp[i]=frac{i}{n}*1+frac{n-i}{n}*(exp[i]+exp[i+1]+1)$
其中$frac{i}{n}*1$表示这一次按对了,直接转移过去,$frac{n-i}{n}*(exp[i]+exp[i+1]+1)$表示这一次按错了,倒退回了$exp[i+1]$然后再转移回$exp[i]$
那么化简+移项就得到了一个可以递推的式子
$exp[i]=frac{(n-i)*(exp[i+1]+1)}{i}+1$
记得乘上$n!$
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=100005; 7 const long long mod=100003; 8 long long inv[N],lit[N],ex[N]; 9 long long n,k,cnt,ans,facs; 10 vector<long long> vc[N]; 11 void prework() 12 { 13 facs=inv[0]=inv[1]=1; 14 for(int i=2;i<=n;i++) 15 { 16 facs=facs*i%mod; 17 inv[i]=((mod-mod/i)*inv[mod%i])%mod; 18 } 19 } 20 int main() 21 { 22 scanf("%lld%lld",&n,&k),prework(); 23 for(int i=1;i<=n;i++) 24 scanf("%lld",&lit[i]); 25 for(int i=1;i<=n;i++) 26 for(int j=i;j<=n;j+=i) 27 vc[j].push_back(i); 28 for(int i=n;i;i--) 29 if(lit[i]) 30 { 31 cnt++; 32 for(int j=0;j<(int)vc[i].size();j++) 33 lit[vc[i][j]]^=1; 34 } 35 if(cnt<=k) 36 printf("%lld",cnt*facs%mod); 37 else 38 { 39 ex[n]=1; 40 for(int i=n-1;i>k;i--) 41 ex[i]=((n-i)*(ex[i+1]+1)%mod*inv[i]%mod+1)%mod; 42 for(int i=1;i<=cnt;i++) 43 ans+=ex[i],ans%=mod; 44 printf("%lld",(ans+k)*facs%mod); 45 } 46 return 0; 47 }
以上是关于解题:2017六省联考 分手是祝愿的主要内容,如果未能解决你的问题,请参考以下文章