Atcoder Grand Contest 023 C 题解
题意
有N个格子,第1到第N-1个格子上有Painting Machines,每一个位于i处的Painting Machine可以将i和i+1位置的格子涂上颜色,将全部格子涂上颜色的时候使用的Painting Machines数目是本次得分,问所有可能性的得分之和。
笺释
从得分的角度考虑,最低得分是[N/2],最高得分是N-1。
那么对于一个给定的N,我们只需要得到达到最低得分的可能情况数和达到最高得分的可能情况数。
设g(i)为得i分的可能情况数。
for i=[n/2]:n-1
ans+=g(i)*i;
一共有n个格子,我们要想全部涂色的话,一定会选择到第N-1个格子上的Painting Machine,因为只有那个可以涂色第n个格子。
除去那个Painting Machine之外,剩余n-2个格子和n-2个Painting Machine是完全对称的,我们就可以利用排列组合求解。
当得i分的时候,我们知道涂完的时候使用i个Painting Machine,因为最右边一定会用去1个,因此左边用去i-1个,每一次都会涂1个格子或者两个格子,要最终涂n-2个格子,也就等价于在i-1次选择中选择使用1或者2,因为每次至少涂1格,所以把这1格先涂上,剩下n-2-(i-1)=n-i-1格没涂,也就是说要选择n-i-1个2,至于剩下的,可能是1,也可能是2,如果是1的话,那就正好是i分,如果是2的话,就说明在达到i分之前就结束了,就小于i分,因此C(i-1,n-i-1)就代表了得分小于等于i分的可能情况,因为是求的组合数,所以C(i-1,n-i-1)*fac(i)*fac(n-i-1)就得到所有方案数,也就是g(i)。
其实我并不会这道题,以上只是对别人题解的理解。=。=
大犇的完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,mod=1e9+7;
int Fac[N],inv[N],n,f[N];
inline int C(int n,int m){
return 1ll*Fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
cin>>n;
int ans=0,li=(n+1)/2;
Fac[0]=inv[0]=inv[1]=1;
for(int i=1;i<=n;i++)Fac[i]=1ll*Fac[i-1]*i%mod;
for(int i=2;i<=n;i++)inv[i]=(mod-1ll*(mod/i)*inv[mod%i]%mod)%mod;
for(int i=2;i<=n;i++)inv[i]=1ll*inv[i]*inv[i-1]%mod;
for(int i=li;i<n;i++)f[i]=1ll*C(i-1,n-1-i)*Fac[i]%mod*Fac[n-1-i]%mod;
for(int i=n-1;i>=li;i--)f[i]=(f[i]-f[i-1]+mod)%mod;
for(int i=n-1;i>=li;i--)ans=(ans+1ll*i*f[i])%mod;
cout<<ans<<endl;
return 0;