[ABC066D] 11
Cloud_Umbrella · · 题解
乍一看,是道数学题。细一想,是道排列组合。
分析
题目明确地说了,
我们用
在写排列组合函数的时候,是要取模的,所以相减可能会得到负数,但答案不可能是负数,所以应该先加上模数再模。
因为数据范围的原因,肯定要用快速幂。代码细节还挺多的。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5,M=1e9+7;
int n,f[N],fact[N];//fact数组用于存阶乘
int Fpower(int x,int y){//快速幂
int k=x,ans=1;
while(y){
if(y&1) ans=ans*k%M;
k=k*k%M;
y>>=1;
}
return ans;
}
int C(int x,int y){
if(x<=0 || y<=0 || x<y) return 0;//不特判会出错
return fact[x]*Fpower(fact[x-y]*fact[y]%M,M-2)%M;
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
cin>>n;
n++;
int start,last;//分别表示重复数字第一和第二次出现的位置
for(int i=1;i<=n;i++){
int x;
cin>>x;
if(f[x]){//注意,要先判断
start=f[x];//f[x]存的是x第一次出现的位置
last=i;
}
f[x]=i;//用于存位置
}
fact[0]=1;
cout<<n-1<<"\n";//要先输出,否则会错!
for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%M;//存下阶乘
for(int i=2;i<=n;i++){
int ans=C(n,i)-C(start+n-last-1,i-1);
ans=(ans+M)%M;//避免出现负数
cout<<ans<<"\n";
}
return 0;//好习惯伴终生
}