Light OJ 1095

本文介绍了一种算法,用于计算在给定数量的整数中,前M个数恰好有K个数位于其原始位置的不同排列的数量。通过组合数学和动态规划方法解决此问题。
题意: 给你 N 个数, 总共有 N! 种排列, 现在 要你统计前 M 个数 刚好 有K 个数 在原来的位置上 的排列个数

思路: 首先 M 中选 K C(m,k);

          则 共 剩下 n - k 个数, 而 n-m 个数中可以允许有数在原来的位置;

    故 枚举 n-m 中有多少个数 在原来的位置上, 剩下的 n - k - i 个数 就是一个错排列了

    (错排列 : D[i] = (i-1) * (D[i-1] + D[i-2] ) ; )

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1000 +131;
const LL MOD = 1000000007;
LL D[maxn], C[maxn][maxn];

void INIT()
{
    C[0][0] = 1;
    for(int i = 1; i < maxn; ++i)
    {
        C[i][0] = C[i][i] = 1;
        for(int j = 1; j < i; ++j)
            C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
    }
    D[1] = 0; D[2] = D[0] = 1;
    for(int i = 3; i < maxn; ++i)
        D[i] = (i-1) * (D[i-1]+D[i-2]) % MOD;
}

LL Solve(LL m, LL k, LL n)
{
    LL Ans = 0;
    for(int i = 0; i <= n-m; ++i)
        Ans = (Ans + C[n-m][i] * D[n-k-i] % MOD) % MOD;
    return C[m][k] * Ans % MOD;
}

int main()
{
    INIT();
    int t;
    LL m, k, n;
    scanf("%d",&t);
    for(int kase = 1; kase <= t; ++kase)
    {
        scanf("%lld%lld%lld",&n, &m,&k);
        printf("Case %d: %lld\n",kase, Solve(m,k,n));
    }
    return 0;
}

 

### 目解析 ZZULI OJ 平台上的1095 是关于时间间隔计算的一道编程。该目主要考察选手对时间和字符串处理的能力,以及如何通过函数实现特定功能。 #### HmsToS 函数 `HmsToS` 函数的作用是将给定的时间(小时 `HH`、分钟 `MM` 和秒数 `SS`)转换为总秒数表示的形式。此函数的核心在于理解时间单位之间的关系: - 一小时等于 3600 秒。 - 一分钟等于 60 秒。 因此,可以通过简单的数学运算完成这一任务[^1]: ```c++ int HmsToS(int h, int m, int s) { return h * 3600 + m * 60 + s; } ``` #### PrintTime 函数 `PrintTime` 函数的功能则是将一个以秒为单位的时间值重新格式化并打印成标准的 `"HH:MM:SS"` 形式。为了满足不足两位时需补充前导零的要求,可以利用 C++ 的 `<iomanip>` 库中的 `setw` 和 `setfill` 来控制输出宽度和填充字符[^2]: ```c++ #include <iostream> #include <iomanip> // 使用 setw 和 setfill 功能需要引入此头文件 using namespace std; void PrintTime(long long total_seconds) { int hours = total_seconds / 3600; // 计算小时部分 int minutes = (total_seconds % 3600) / 60; // 剩余的部分除以60得到分钟 int seconds = total_seconds % 60; // 取模获得剩余秒钟 cout << setw(2) << setfill('0') << hours // 输出小时,设置宽度为2,不足则用'0'补齐 << ":" // 添加分隔符":" << setw(2) << setfill('0') << minutes // 同理输出分钟 << ":" << setw(2) << setfill('0') << seconds // 输出秒数 << endl; } ``` 以上两个函数分别实现了从时间到秒数的转化以及从秒数回到标准化时间显示的过程。按照目要求,在实际提交代码的时候只需提供这两个函数的具体定义即可。 另外需要注意的是,由于可能存在多组测试数据的情况,程序应能够连续读取输入直到结束,并针对每一组给出相应的结果输出。 ### 输入输出样例说明 假设一组输入如下所示: ``` 1 12 30 45 ``` 其中第一行为实例数量 n=1 表明只有一组待测数据;第二行给出了具体的一个时刻即十二点三十分四十五秒。那么对应的输出应该是这个时刻所代表的总的秒数值再经过反向转换回原始形式展示出来,也就是保持原样的返回因为这里我们只是单纯演示流程而非真正做差操作: ``` 12:30:45 ``` 如果存在两组或多组这样的情况,则依次类推单独处理每一条记录之后统一按指定样式呈现最终答案列表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值