传送门
题目思路很好想,用dp[i][j][k]表示第i个数,a[i]放j,b[i]放k的方案数.
暴力转移的话复杂度是O(m×n4),用前缀和可以优化到O(m×n2).
dp[i][j][k] = sum{dp[i-1][1->j][k->n]}
代码
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int mod = 1e9+7;
inline void read(int &a){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){
x=x*10+ch-'0';ch=getchar();}
a = x*f;
}
LL dp[11][1010][1010],sum[1010];
int main(){
int n,m;
cin >> n >> m;
LL ans = 0;
fir(i,1,n){
fir(j,i,n){
dp[1][i][j] = 1;
if(m == 1) ans = ( dp[1][i][j] + ans ) % mod;
}
}
fir(i,2,m){
mem(sum,0);
fir(j,1,n){
LL tmp = 0;
afir(k,n,j){
tmp = (tmp + dp[i-1][j][k])%mod;
sum[k] = (sum[k+1] + tmp)%mod;
dp[i][j][k] = sum[k];
if(i == m) ans = (ans+dp[i][j][k])%mod;
}
}
}
cout << ans << endl;
return 0;
}