UVA - 11077 Find the Permutations(置换)

本文通过一道关于序列排列的问题引入动态规划(DP)算法的应用。针对一个特定的数学问题——求解长度为N的序列中,有多少种排列方式可以通过K次最小交换变为升序排列,文章详细介绍了如何从置换角度出发,利用DP算法解决该问题,并给出了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题的代码在刘老师的白书上已给出, 这里也是参考刘老师的代码,加上自己的一点理解。
题目地址
题意:
对于一个长度为N的序列, 这个序列的可能排列组合有N!种。每种组合序列中,可以最小交换K次使序列达到升序。现在给你一个N和K,问在N!种序列中有多少个序列使最小的交换次数等于K。
思路:
如果单纯的暴力是肯定会超时的(N!的复杂度!!!!)。
可以从置换的角度考虑。
想一下达到升序的时候整个序列的循环节都是1,那对于一个循环节为K的序列转换到1要交换多少次? 当然是(k-1)次啊!(模拟一下就知道了),那是不是说对长度为N,循环节有K个的时候要交换的次数为(N-K)次!
那再看一眼数据范围, 1<=N<=21, 0<=K < N
打表!dp!
可以得到递推式 dp[i][j] = dp[i-1][j]+dp[i-1][j-1]*(i-1);
dp[i-1][j]表示i放在i应该在的位置上,然后前面i−1个还是需要j次交换 。
dp[i-1][j-1]表示第i个放前面i−1个中的一个位置上,然后那个放第i个位置上,这样就多一次交换 。


#include       <cstdio>
#include     <iostream>
#include        <cmath>
#include          <map>
#include        <queue>
#include       <vector>
#include          <ios>
#include       <bitset>
#include        <stack>
#include      <cstring>
#include      <iomanip>
#include    <algorithm>
#define lowbit(x) ((x)&(-x))
#define mp make_pair
#define pb push_back
#define Pi acos(-1.0)
#define E exp(1.0)
#define sz(a) (int)(a).size()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ud;
typedef pair<int, int> PI;
const double eps = 1e-6;
const ll lmod = 1e9+7;
const int maxn = 105;
int Case = 1, cnt, n, m;
ull f[maxn][maxn];

int main() {
    ios::sync_with_stdio(false);
    memset(f, 0, sizeof(f));
    f[1][0] = 1;
    for(int i = 2; i <= 21; i++) {
        for(int j = 0; j <= 21; j++) {
            f[i][j] = f[i-1][j];
            if(j > 0)   f[i][j] += f[i-1][j-1]*(i-1);
        }
    }
    while(cin>>n>>m&&(n+m))
    cout<<f[n][m]<<endl;
    return 0;
}

必须要用unsigned long long, 不然会爆!

### 关于代谢组学中的 PLS-DA 置换检验图 偏最小二乘判别分析 (Partial Least Squares Discriminant Analysis, PLS-DA) 是一种广泛应用于代谢组学数据分析的技术,用于分类样本并识别潜在的生物标志物。为了评估模型的有效性和防止过拟合,通常会采用置换检验 (Permutation Test),通过随机打乱类别标签来计算模型性能指标的变化。 以下是 Python 和 R 的实现方法: --- #### 使用 Python 实现 PLS-DA 置换检验图绘制 Python 提供了 `sklearn` 库来进行 PLS 回归建模,并可以通过自定义函数完成置换检验和绘图功能。 ```python import numpy as np from sklearn.cross_decomposition import PLSRegression from sklearn.model_selection import cross_val_score import matplotlib.pyplot as plt from scipy.stats import pearsonr def permutation_test(X, y, n_permutations=1000): """ 执行 PLS-DA 的置换检验。 参数: X: 特征矩阵 y: 类别标签向量 n_permutations: 置换数 返回: observed_scores: 原始数据上的交叉验证得分 permuted_scores: 随机化后的平均交叉验证得分列表 """ pls_da = PLSRegression(n_components=2) observed_scores = cross_val_score(pls_da, X, y, cv=5).mean() permuted_scores = [] for _ in range(n_permutations): y_shuffled = np.random.permutation(y) score = cross_val_score(pls_da, X, y_shuffled, cv=5).mean() permuted_scores.append(score) return observed_scores, permuted_scores # 数据加载与预处理省略... observed, permuted = permutation_test(X, y) plt.figure(figsize=(8, 6)) plt.hist(permuted, bins=30, alpha=0.75, color='blue', label="Permuted Scores") plt.axvline(observed, color='red', linestyle='dashed', linewidth=2, label=f'Observed Score ({observed:.2f})') plt.title('PLS-DA Permutation Test Results', fontsize=16) plt.xlabel('Cross-validation Accuracy', fontsize=14) plt.ylabel('Frequency', fontsize=14) plt.legend(fontsize=12) plt.show() ``` 上述代码展示了如何利用 `cross_val_score` 函数进行交叉验证以及通过多随机排列目标变量 `y` 来模拟零假设下的分布情况[^2]。 --- #### 使用 R 实现 PLS-DA 置换检验图绘制 在 R 中可以借助 `ropls` 或 `mixOmics` 包轻松构建 PLS-DA 模型,并执行置换测试。 ```R library(ropls) set.seed(123) # 构造示例数据集 data(sacurine) X <- sacurine$dataMatrix Y <- factor(sacurine$sampleMetadata[, "gender"]) # 创建原始模型 model_original <- oplsdas(X, Y, predI = 2, orthoI = 0) # 进行置换检验 permut_results <- permutest(model_original, times = 1000) # 绘制结果 plot(permut_results, type = "histogram", main = "PLS-DA Permutation Test", xlab = "Q-squared Value", col = c("lightgray", "red")) legend("topright", legend=c("Permuted Q²", "Original Q²"), fill=c("lightgray", "red")) ``` 此脚本使用 `ropls::oplsdas()` 方法建立基础模型,并调用内置函数 `permutest()` 自动生成置换统计图表[^3]。 --- ### 对置换检验图的解释 置换检验的核心在于比较实际观测到的模型表现(如 $Q^2$ 或 CV-Accuracy)与基于随机重排类别的预期值之间的差异程度。如果真实分数显著高于大多数置换所得数值,则表明当前分组结构确实存在而非偶然形成[^4]。 具体而言,在直方图上可以看到所有可能因噪声引起的最大预测能力范围;而红线代表未经扰动的数据集中所获得的最佳匹配度。两者差距越大说明该分类体系越可靠可信。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值