E-Remove
表示前 个数,删除 个的方案数
假如每个数字都是不重复的,那么很简单, ,并且还阔以直接用组合数算出来,就是
但是现在有重复的了,通过第一个样例就可以看出来
我们写一个一般一点的数列
1 2 3 4 5 6 7
这 个数里面删除 个数,问答案有多少种?
这个的答案是 ,我们来看这个 是怎么来的:
假如不考虑重复的情况,答案就是 ,然后要删除重复的
重复的就是以下情况:
删除圆圈里的这 个数,数列都变成了 1 2 3 4 ,而这种情况只删除了 个数,还要再在前面 1 2 3 4 中删除 个数,就是
所以总的答案就是
也想当于
这样就把重复的减去了
只要满足这种重复的条件,减去就行了
#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define outdp(x,y) cout<<"dp["<<(x)<<"]["<<(y)<<"]="<<dp[(x)][(y)]
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
LL dp[maxn][11];
int last[11];//¼Ç¼Õâ¸öÊýÉÏÒ»´Î³öÏÖµÄλÖÃ
int main()
{
int N,M,K;
while(cin>>N>>M>>K)
{
memset(last,0,sizeof(last));
memset(dp,0,sizeof(dp));
for(int i=0;i<=N;i++)dp[i][0]=1;//Ò»¸ö¶¼²»É¾ÓÐÒ»ÖÖÇé¿ö
for(int i=1;i<=N;i++)
{
int t;
scanf("%d",&t);
for(int j=1;j<=M&&j<=i;j++)
{
dp[i][j]+=dp[i-1][j]+dp[i-1][j-1];
if(last[t])//Èç¹û³öÏÖͬÑùµÄ£¬¾ÍҪɾȥ
{
int len=i-last[t];//Á½¸öͬÑùµÄÊýÖÐҪɾ³ýµÄ¸öÊý
if(j>=len)dp[i][j]-=dp[i-len-1][j-len];
}
if(dp[i][j]>MOD||dp[i][j]<0)dp[i][j]=(dp[i][j]%MOD+MOD)%MOD;
}
last[t]=i;
}
cout<<dp[N][M]<<endl;
}
}
J-Different Integers
题意:求区间中不同值的个数
这道题的思路是这样的:
从左到右,每个数只在他最后出现的地方标记一下,如果新出现了这个数,那么就是这个数加 ,那么这个数在上一个位置就减 成为 ,就像这样:
每次的询问 ,只要有这样的一张表就好得到答案
所以用树状数组啥的维护一哈就行了
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const LL maxn=2e5+5;
LL a[maxn],tree[maxn],Ans[maxn];
LL N,Q;
struct AAA
{
LL L,R,id;
bool operator<(const AAA &a)const
{
return R<a.R;
}
};
AAA qry[maxn];
void Add(int pos,int v)
{
for(int i=pos; i<=2*N; i+=(i&-i))
{
tree[i]+=v;
}
}
LL getsum(int pos)
{
LL res=0;
for(int i=pos; i>=1; i-=(i&-i))
{
res+=tree[i];
}
return res;
}
LL vis[maxn];
int main()
{
while(scanf("%d%d",&N,&Q)!=EOF)
{
memset(tree,0,sizeof(tree));
for(int i=1; i<=N; i++)scanf("%d",&a[i]),a[i+N]=a[i];
for(int i=1; i<=Q; i++)
{
int L,R;
scanf("%d%d",&qry[i].R,&qry[i].L);
qry[i].R+=N;
qry[i].id=i;
if(qry[i].L>qry[i].R)swap(qry[i].L,qry[i].R);
}
sort(qry+1,qry+1+Q);
N<<=1;
memset(vis,0,sizeof(vis));
int now=0;
for(int i=1;i<=Q;i++)
{
int L=qry[i].L,R=qry[i].R;
for(;now<R;)
{
now++;
if(vis[a[now]]==0)
{
vis[a[now]]=now;
Add(now,1);
}
else
{
Add(vis[a[now]],-1);
vis[a[now]]=now;
Add(now,1);
}
}
Ans[qry[i].id]=getsum(R)-getsum(L-1);
}
for(int i=1; i<=Q; i++)printf("%d\n",Ans[i]);
}
}