模拟赛 Problem 2 不等数列(num.cpp/c/pas)

时间:2023-03-09 17:44:04
模拟赛 Problem 2 不等数列(num.cpp/c/pas)

Problem 2 不等数列(num.cpp/c/pas)

【题目描述】

将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,有多少个排列恰好有k个“<”。答案对2012取模。

【输入格式】

第一行2个整数n,k。

【输出格式】

一个整数表示答案。

【样例输入】

5 2

【样例输出】

66

【数据范围】

对于30%的数据:n <= 10

对于100%的数据:k < n <= 1000,

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mod 2012
#define MAXN 1010
using namespace std;
int n,k,ans;
int vis[MAXN],num[MAXN];
bool judge(){
int bns=;
for(int i=;i<=n;i++)
if(num[i]>num[i-]) bns++;
if(bns==k) return true;
else return false;
}
void dfs(int now){
if(now==n+){
if(judge())
ans=(ans+)%mod;
return ;
}
for(int i=;i<=n;i++)
if(!vis[i]){
vis[i]=;num[now]=i;
dfs(now+);
vis[i]=;
}
}
int main(){
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
scanf("%d%d",&n,&k);
dfs();
cout<<ans<<endl;
}

用来打表的暴力

打完表后会发现是一个这样的一个东西:

模拟赛 Problem 2 不等数列(num.cpp/c/pas)

然后就可以找规律了。然后并不肿么样。

最后调转思路,转到了DP上。

f[i][j]表示在前i个里面加入j个‘<’的方案数,那么就有:

  f[i][j]=(f[i-1][j]*(j+1)+f[i-1][j-1]*(i-j))%mod;

然后就完成了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mod 2012
using namespace std;
int n,k;
int f[][];
int main(){
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) f[i][]=;
for(int i=;i<=n;i++)
for(int j=;j<=min(i-,k);j++)
f[i][j]=(f[i-][j]*(j+)+f[i-][j-]*(i-j))%mod;
printf("%d",f[n][k]);
}