[AGC045D] Lamps and Buttons 题解
[AGC045D] Lamps and Buttons 题解
首先,由于排列生成随机,所以最优决策就是不决策(反正你也不知道),也就是,让 Snuke 从左往右依次按。
那么,什么情况下 Snuke 会输呢?我们可以把每个
现在我们就要求
因为要成环,我们就通过插入来考虑。每次插入一个点
如果按照我一开始每次单独求
代码:
#include<bits/stdc++.h> using namespace std; const int mod = 1e9+7; const int N = 1e7+10, M = 5050; int fac[N], inv[N]; inline int C(int n, int m){ if(n<0 || m<0 || n<m) return 0; return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod; } int n, m; inline int fpow(int a, int b){ a%=mod; int ret = 1; while(b){ if(b & 1){ ret = (1ll*ret*a)%mod; } b>>=1; a = (1ll*a*a)%mod; } return ret; } void prework(){ fac[0] = 1; for(int i = 1; i<=n; ++i){ fac[i] = (1ll*fac[i-1]*i)%mod; } inv[n] = fpow(fac[n], mod-2); for(int i = n-1; i>=0; --i){ inv[i] = (1ll*inv[i+1]*(i+1))%mod; } } inline int calc(int a, int b, int c){ return 1ll*a*fac[a+b+c]%mod*fac[a+b-1]%mod*inv[a+b]%mod; } int ans; int main(){ scanf("%d%d", &n, &m); prework(); int a, b, c; for(int t = 1; t<=m+1; ++t){ for(int i = 0; i<t; ++i){ a = t-i-1, b = n-m, c = m-t; if(t == m+1) c = 0; int fu = (i&1)?-1:1; ans = (1ll*ans+1ll*fu*C(t-1, a)*calc(a, b, c)%mod)%mod; ans = (ans+mod)%mod; } } printf("%d\n", ans); return 0; }