分析
一眼的数学题。因为原问题并不好做,按照正难则反,我们先考虑容斥。定义 表示至少有 对情侣坐在了一起。那么 。 为容斥系数。考虑单独的 如何求解。那么我们发现这是在求一个圆排列,根据 元素构成的圆排列方式为 。所以 。 表示 个有标号的元素的圆排列方式。最后 。注意一下空间限制,对于 要预处理。时间复杂度为 。
代码
#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; }