Welcome to Liukejie's |

liukejie

园龄:1年8个月粉丝:5关注:11

题解:AT_arc077_b [ABC066D] 11

思路

组合数学题。

题目说有 n+1 个数且 [1,n] 都出现过,则只有 1 个数重复。如果不算重复,则方案为 Ckn+1。接着我们考虑容斥

我们设这个重复的数字第一次为 l,最后一次出现的位置为 r。则 lr 都无解,那么重复计算的子序列个数就是 Ck1l+ni1。答案相减即可。

代码

#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 @   liukejie  阅读(2)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起