【BZOJ2699】更新 动态规划
【BZOJ2699】更新
Description
对于一个数列A[1..N],一种寻找最大值的方法是:依次枚举A[2]到A[N],如果A[i]比当前的A[1]值要大,那么就令A[1]=A[i],最后A[1]为所求最大值。假设所有数都在范围[1, K]内,按上面的步骤执行,有多少个长度N的数列满足A[1]被更新的次数恰好为P呢?
Input
本题有多组数据。输入第一行一个数T为数据组数,下面T行每行依次三个数N、K和P。
Output
对每组数据输出一行,为方案数模1000000007的值。
输入 | 输出 | 解释 |
3
4 3 2
2 3 1
3 4 1
|
6
3
30
|
对第一组数据N=4, K=3, P=2, 所有满足的序列有下面六种:
1) {1,1,2,3} 2) {1,2,1,3}
3) {1,2,2,3} 4) {1,2,3,1}
5) {1,2,3,2} 6) {1,2,3,3}
|
数据范围
前20%的数据满足T ≤ 5
前50%的数据满足1 ≤ N ≤ 50,1 ≤ K ≤ 100
对100%的数据,T ≤ 1000,1 ≤ N ≤ 150,0 ≤ P < N,1 ≤ K ≤ 300
题解:傻题。。
用f[i][j][k]表示前i个数,最大值为j,已经被更新了k次的方案数。然后用前缀和优化转移即可。
#include <cstdio> #include <cstring> #include <iostream> typedef long long ll; const ll P=1000000007; int T,n,m,p; int f[160][310][160]; int main() { int i,j,k; for(i=1;i<=300;i++) f[1][i][0]=i; for(i=2;i<=150;i++) { for(k=0;k<=150;k++) { for(j=1;j<=300;j++) { if(k) f[i][j][k]=f[i-1][j-1][k-1]; f[i][j][k]=(f[i][j][k]+1ll*j*(f[i-1][j][k]-f[i-1][j-1][k]+P)%P+f[i][j-1][k])%P; } } } scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&p); printf("%d\n",f[n][m][p]); } return 0; }
| 欢迎来原网站坐坐! >原文链接<