【7.10校内test】T2不等数列

【题目连接luogu】c++

此题在luogu上模数是2015,考试题的模数是2012。测试

而后这道题据说好多人是打表找规律的(就像7.9T2同样)(手动滑稽_gc)spa

另外手动设计

sy,每次测试都无心之间bibi正解,而后说本身是不会作是个什么骚气操做。code

因此咱们来看真.题解;blog

SOLUTION:get

首先,输入莫得什么好说的;it

固然想用快读咱也拦不住(就是想用咬我啊);io

咱可能最近由于学长讲了一道DP,印象比较深入,因此咱竟然看到这道题就想到正解应该是DP了!?class

接下来就是设计DP状态了:

dp[i][j]表示i个数,恰有j个‘<’的排列方案数;

转移就很神奇颇有意思了:

当咱们已知dp[1~i-1][1~k]时,咱们考虑求dp[i][j];

当数从i-1~i时,显然数列增长的数是大于1~i-1的(莫得由于什么,很差解释,感性理解);咱们考虑把i这个数加在哪里:

①加在序列的最左侧:

由于i>1~i-1的任何一个数,因此必定是‘>’,所以对‘<’的多少没有影响;

②加在序列最右侧:

同理由于i>1~i-1任何一个数,因此当将i放在序列最右侧时,必定会增长一个‘<’;

③加在一个‘<’的中间:

实际上不会增长‘<’,所以不会对答案产生影响qwq;

④加在一个‘>’中间:

增长了一只‘<’。

因此由此咱们能够推出状态转移方程:

当i加在第①③种状况时,不会产生新的‘<’,所以咱们须要由dp[i-1][j]推过来。

能够计算1~i-1的序列中,共有j个‘<’号,而后还有①状况中的一种,共有j+1种状况是添加后不增长‘<’的,因此dp[i][j]+=dp[i-1][j]*(j+1);

当i加在第②④种状况时,会产生新的'<',所以咱们也须要由dp[i-1][j-1]推得:

④状况:咱们知道当前状况下1~i-1中共有j-1个‘>’,总共的符号数为i-2个,所以其中‘>’数为i-2-(j-1)=i-j-1个,再加上②状况的一种,因此共有i-j个能够产生一个新的‘<’;所以dp[i][j]+=dp[i-1][j-1]*(i-j);

转移方程:dp[i][j]=dp[i-1][j]*(j+1)+dp[i-1][j-1]*(i-j);//注意取模

而后是初始状态:

当咱们有0个‘<’时,不管有几个数,这些数必须严格升序排列,也就是只有一种排列是知足有0个‘<’的;所以初始化:dp[1~n][0]=1;

最后的答案显然就是dp[n][k]了;

CODE:

#include<bits/stdc++.h>

using namespace std;

int n,k;
int dp[1010][1010];

int main(){
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++) dp[i][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++){
            dp[i][j]=(dp[i-1][j]*(j+1)%2015+dp[i-1][j-1]*(i-j)%2015)%2015;
        }
    }
    printf("%d",dp[n][k]);
    return 0;
}

end- 

相关文章
相关标签/搜索