【题解】[Codechef] Beautiful Permutation
传送门#
以此纪念我场切的 dp。
这种计数的类型一看就很 dp 的样子。考场上一开始设的 dp 状态是
当
当
可以把第一维滚掉,这样就做到了时间复杂度
我们发现记前
当
当
时间复杂度为
#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
#define mod 1000000007
using namespace std;
const int N = 305;
int n, m, a[N], cnt[N], dp[N][N][N][2], sum;
signed main() {
freopen("2475.in", "r", stdin);
freopen("2475.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
For(i,1,n) {
cin >> a[i];
if(!a[i]) continue;
cnt[a[i] & 1]++;
}
cnt[0] = n / 2 - cnt[0];
cnt[1] = ceil(1.0 * n / 2) - cnt[1];
dp[0][0][0][0] = dp[0][0][0][1] = 1;
For(i,1,n) {
if(!a[i]) sum++;
For(j,1,m) {
For(k2,0,min(sum, cnt[1])) {
if(a[i] != 0) {
if(a[i] & 1) {
dp[i][j][k2][1] = (dp[i][j][k2][1] + (dp[i-1][j-1][k2][0] + dp[i-1][j][k2][1]) % mod) % mod;
} else {
dp[i][j][k2][0] = (dp[i][j][k2][0] + (dp[i-1][j][k2][0] + dp[i-1][j-1][k2][1]) % mod) % mod;
}
continue;
}
if(cnt[0] - (sum - k2) + 1 > 0) dp[i][j][k2][0] = (dp[i][j][k2][0] + ((cnt[0] - (sum - k2) + 1) * (dp[i-1][j-1][k2][1] + dp[i-1][j][k2][0]) % mod) % mod) % mod;
if(k2 != 0) dp[i][j][k2][1] = (dp[i][j][k2][1] + ((cnt[1] - k2 + 1) * (dp[i-1][j-1][k2-1][0] + dp[i-1][j][k2-1][1]) % mod) % mod) % mod;
}
}
}
cout << (dp[n][m][cnt[1]][0] + dp[n][m][cnt[1]][1]) % mod << '\n';
return 0;
}
作者:Daniel-yao
出处:https://www.cnblogs.com/Daniel-yao/p/18474614
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】