6575: 11(组合数)

You are given an integer sequence of length n+1, a1,a2,…,an+1, which consists of the n integers 1,…,n. It is known that each of the n integers 1,…,n appears at least once in this sequence.
For each integer k=1,…,n+1, find the number of the different subsequences (not necessarily contiguous) of the given sequence with length k, modulo 109+7.
Notes
If the contents of two subsequences are the same, they are not separately counted even if they originate from different positions in the original sequence.
A subsequence of a sequence a with length k is a sequence obtained by selecting k of the elements of a and arranging them without changing their relative order. For example, the sequences 1,3,5 and 1,2,3 are subsequences of 1,2,3,4,5, while 3,1,2 and 1,10,100 are not.

Constraints
1≤n≤105
1≤ai≤n
Each of the integers 1,…,n appears in the sequence.
n and ai are integers.

 

 

输入

Input is given from Standard Input in the following format:
n
a1 a2 ... an+1

 

输出

Print n+1 lines. The k-th line should contain the number of the different subsequences of the given sequence with length k, modulo 109+7.

 

样例输入

3
1 2 1 3

 

样例输出

3
5
4
1

 

提示

There are three subsequences with length 1: 1 and 2 and 3.
There are five subsequences with length 2: 1,1 and 1,2 and 1,3 and 2,1 and 2,3.
There are four subsequences with length 3: 1,1,3 and 1,2,1 and 1,2,3 and 2,1,3.
There is one subsequence with length 4: 1,2,1,3.

 

 

 

有n+1个数,其中包含n个不同的数,只有一个数出现两次。问他的长度为k的子序列有多少种。

假如重复的数为t,t左边包含x个数,两个t之间包含z个数,t右边包含y个数。x    t   z   t   y

如果没有相同的数c(n+1,k),重复选过的数有:

 

x中选0个,选t,y中选k - 1个  +

x中选1个,选t,y中选k - 2个  +

..............................................  +

x中选k - 2个,选t,y中选1个  +

x中选k - 1个,选t,y中选0个  。

总和就是C(x+y,k - 1);

 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
const int mod = 1e9+7;
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
int a[100005], vis[100005];
ll fac[1000006], inv[1000006];
 
ll init(){
    fac[0] = 1;
    for (int i = 1; i < 1000006; i++)
        fac[i] = fac[i - 1] * i % mod;
    inv[1000006 - 1] = qpow(fac[1000006 - 1], mod - 2);
    for (int i = 1000006 - 2; i >= 0; i--)
        inv[i] = inv[i + 1] * (i + 1) % mod;
    return 0;
}
ll c(ll n, ll m){
    if (n < m) return 0;
    return fac[n] * inv[m] % mod * inv[n - m] % mod;
}

int main(){
	init();
	memset(vis, 0, sizeof(vis));
	int n, l, r;
	scanf("%d", &n);
	for(int i = 1; i <= n + 1; i++){
		int x;
		scanf("%d", &x);
		if(!vis[x]){
			vis[x] = i;
		}
		else{
			l = vis[x];
			r = i;
		}
	}
	ll x = l - 1;
	ll y = n - r + 1;
	for(int i = 1; i <= n + 1; i++){
		ll ans = (c(n + 1, i) - c(x + y, i - 1) + mod) % mod;
		printf("%lld\n", ans);
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值