最后的晚餐(dinner)
最后的晚餐(dinner)
https://ac.nowcoder.com/acm/problem/19857
分析
一眼的数学题。因为原问题并不好做,按照正难则反,我们先考虑容斥。定义 表示至少有
对情侣坐在了一起。那么
。
为容斥系数。考虑单独的
如何求解。那么我们发现这是在求一个圆排列,根据
元素构成的圆排列方式为
。所以
。
表示
个有标号的元素的圆排列方式。最后
。注意一下空间限制,对于
要预处理。时间复杂度为
。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
int read() {
int x = 0,f = 0;char ch = getchar();
while(!isdigit(ch)) {if(ch=='-')f=1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
return f?-x:x;
}
const int N = 30000010,P = 1e9 + 7;
int qpow(int a,int b) {
int x = 1;
for(;b;b>>=1,a = 1LL * a * a % P) {
if(b & 1) x = 1LL * a * x % P;
}
return x;
}
int ans = 0,fac[N * 2],ifac[N];
int C(int n,int m) {return 1LL * fac[n] * 1LL * ifac[m] % P * ifac[n - m] % P;}
signed main() {
LL n = read();
if(n == 0 || n == 1) {printf("0\n");return 0;}
fac[0] = 1;
for(int i = 1;i <= n * 2;i++) {fac[i] = 1LL * fac[i-1] * i % P;}
ifac[n] = qpow(fac[n],P - 2);
for(int i = n - 1;i >= 0;i--) {ifac[i] = 1LL * ifac[i + 1] * (i + 1) % P;}
for(int i = n,Pow = qpow(2,n),Fac = fac[n - 1]; i >= 0 ; Pow = 1LL * Pow * ifac[2] % P,Fac = 1LL * Fac * (2 * n - i) % P,i--) {
if(i&1) ans = ((1LL * ans - (1LL * C(n,i) * Pow % P * 1LL * Fac % P)) % P + P) % P;
else ans = ((1LL * ans + (1LL * C(n,i) * Pow % P * 1LL * Fac % P)) % P + P) % P;
// cout << ans << endl;
// cout << Fac << " " << Pow << endl;
}
printf("%d\n",(ans % P + P) % P);
return 0;
}数学 文章被收录于专栏
关于多项式

