题解: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);
	}
}
posted @ 2024-11-02 09:18  liukejie  阅读(2)  评论(0编辑  收藏  举报