DTOJ 4030: 排列计数
【题目描述】
求有多少个1到
考虑$k$和$n$都不大考虑DP。$f[i][j]$表示$n=i$,$k=j$时的答案。
那么考虑怎么转移,考虑将$i$插入长度为$i-1$的排列中,对答案的影响。有$f[i][j]=f[i-1][j]*(j+1)+f[i-1][j-1]*(i-j)$
$f[i-1][j]*(j+1)$表示将$i$插入后满足要求的数对没有变多,因为$i$大于$i-1$排列中的任意一个,所以将$i$插入$j$个以满足的数对中的任意一个都不会使得满足条件的数对变多,又或者直接将$i$放在第一个。
$f[i-1][j-1]*(i-j)$表示将$i$插入后数对变多了,也是因为$i$大于$i-1$排列中的任意一个,所以只要不插入到$j-1$个已经满足的数对中即可,那么就会有$(i-2)-(j-1))$,加上最后一个位置就是$i-j$了。
初值为$f[i][0]=1$,可以用打表和DP式子来判断。
#include#include =(f[i-1][j]*(j+1)%p+(f[i-1][j-1]*(i-j))%p)%p; printf("%d\n",f[n][k]); return 0; }#include #include #define N 1005 #define p 2012 using namespace std; int n,k,f[N][N]; int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) f[i][0]=1; for(int i=1;i<=n;i++) for(int j=1;j) f[i][j]
总结:
计数类问题,一般都是排列组合和DP。尤其是在数据范围不太大,DP状态可以表示时,要考虑DP。
其实也不能算是DP,更准确的说应该是递推,考虑从$i$到$i+1$的答案变化。