考虑最上面每个位置的数对答案的贡献
然后就很容易发现:
如果有n层,位置 i 的数对答案的贡献就是C( n-1,i )
然后就有很显然的贪心做法:
越大的数放越中间,这样它的贡献就会尽可能的大
然后考虑算C( i,j )
因为n很大,模数很小
所以要用lucas定理求C
C(n,m)= C(n/mo,m/mo)*C(n%mo,m%mo)
当C比较小的时候可以直接用阶乘和阶乘逆元算出
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) f=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=1e6+7,mo=1e4+7; int n; ll inv[mo],fac[mo];//注意long long inline void pre()//预处理阶乘和阶乘逆元 { fac[0]=1; for(int i=1;i<mo;i++) fac[i]=fac[i-1]*i%mo; inv[0]=inv[1]=1; for(int i=2;i<mo;i++) inv[i]=(mo-mo/i)*inv[mo%i]%mo; for(int i=1;i<mo;i++) inv[i]=inv[i]*inv[i-1]%mo;//求阶乘逆元 } inline ll C(ll x,ll y) { if(x<y) return 0; if(x<mo&&y<mo) return fac[x]*inv[y]%mo*inv[x-y]%mo;//C较小时直接求 return C(x%mo,y%mo)*C(x/mo,y/mo)%mo; } inline ll f(ll x) { return x>=mo ? x-mo : x; }//对不超过2*mo的数取模这样会快点 int main() { pre(); n=read(); ll ans=0; for(int i=1;i<=n;i++) ans=f( ans + C(n-1,(i-1)>>1)*i%mo ); printf("%lld",ans); return 0; }
原文地址:https://www.cnblogs.com/LLTYYC/p/9803165.html
时间: 2024-10-20 02:38:18