题解:AT_arc077_b [ABC066D] 11
思路
组合数学题。
题目说有 \(n+1\) 个数且 \([1,n]\) 都出现过,则只有 \(1\) 个数重复。如果不算重复,则方案为 \(\large C_{k}^{n+1}\)。接着我们考虑容斥
我们设这个重复的数字第一次为 \(l\),最后一次出现的位置为 \(r\)。则 \(l \sim r\) 都无解,那么重复计算的子序列个数就是 \(\large {C_{k-1}^{l+n-i-1}}\)。答案相减即可。
代码
#include<bits/stdc++.h>
#define int long long
#define rep(i, l, r) for(int i = l; i <= r; ++ i)
#define per(i, r, l) for(int i = r; i >= l; -- i)
using namespace std;
const int N = 2e5 + 5, MOD = 1e9 + 7;
int n, a[N], k, vis[N];
int fac[N], inv[N];
int ksm(int a, int b)
{
int res = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a % MOD;
a = a * a % MOD;
}
return res;
}
int C(int x, int y)
{
if(x < y) return 0;
return fac[x] * inv[y] % MOD * inv[x - y] % MOD;
}
void init()
{
fac[0] = inv[0] = 1;
rep(i, 1, n)
{
fac[i] = fac[i - 1] * i % MOD;
inv[i] = ksm(fac[i], MOD - 2);
}
}
main()
{
scanf("%lld", &n); ++ n; init();
rep(i, 1, n)
{
scanf("%lld", &a[i]);
if(!vis[a[i]]) vis[a[i]] = i;
else k = i - vis[a[i]] + 1;
}
rep(i, 1, n)
{
int ans = C(n, i) % MOD;
int cnt = C(n - k, i - 1) % MOD;
printf("%lld\n", (ans + MOD - cnt) % MOD);
}
}