码蹄集 - MT2013 · 饿饿︕饭饭︕ - 解题思路版本

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了码蹄集 - MT2013 · 饿饿︕饭饭︕ - 解题思路版本相关的知识,希望对你有一定的参考价值。

传送门


饿饿!饭饭!

时间限制:1秒
空间限制:64M


题目描述

嗯哼,小码哥在新的一年里不会忘记身为干饭人的初心!

众所周知,小码哥非常不喜欢一直吃同样的东西,但由于理想与现实的差距,食堂在这n天里只会供应k种餐食。

在一天吃3餐的情况下,前w天一共w\\times3w×3顿饭小码哥不希望有任何一顿重复。现在请问食堂有多少种方案可以满足超级可爱乖巧的小码哥的需要。


输入描述

第一行,三个整数n,k,w表示n天内食堂只会供应k种餐室,w的意义详见题面


输出描述

输出一行一个数,表示满足小码哥需要的方案数。


样例一

输入

5 4 1

输出

24

题目分析

看题后不禁思索:这个 n n n有啥用呢?食堂提供 n n n天的饭,如果小码哥想吃 w w w天且 w > n w>n w>n的话是不是就没有可行方案了呢?

算了,先骗一波数据吧。

#include <bits/stdc++.h>
using namespace std;
int main() 
    int n, k, w;
    cin >> n >> k >> w;
    assert(n >= k);
    return 0;

运行结果:

Compile Successfully.

- Test Point #0: Wrong Answer, Time = 2 ms, Memory = 172 KB, Score = 0
- Test Point #1: Wrong Answer, Time = 2 ms, Memory = 0 KB, Score = 0
- Test Point #2: Wrong Answer, Time = 2 ms, Memory = 148 KB, Score = 0
- Test Point #3: Wrong Answer, Time = 2 ms, Memory = 156 KB, Score = 0
- Test Point #4: Wrong Answer, Time = 2 ms, Memory = 148 KB, Score = 0
- Test Point #5: Wrong Answer, Time = 2 ms, Memory = 184 KB, Score = 0
- Test Point #6: Wrong Answer, Time = 2 ms, Memory = 148 KB, Score = 0
- Test Point #7: Wrong Answer, Time = 2 ms, Memory = 216 KB, Score = 0
- Test Point #8: Wrong Answer, Time = 2 ms, Memory = 152 KB, Score = 0
- Test Point #9: Wrong Answer, Time = 2 ms, Memory = 152 KB, Score = 0

Wrong Answer, Time = 20 ms, Memory = 216 KB, Score = 0

喔!没有运行错误耶。也就是说 n n n一定是 ≥ w \\geq w w的,我们只需要考虑 k k k w w w的关系即可。

既然要吃 w w w天,那就要吃 w ∗ 3 w*3 w3顿饭。所以输入了 w w w后不妨直接 w ∗ = 3 w*=3 w=3

那么题目意思就是:在 k k k种选择种选 w w w(已×3)种有多少种不同的方案。

这不就是典型的排列数吗?公式 A k w = ( k ) × ( k − 1 ) × ⋯ × ( k − w + 1 ) A_k^w = (k) \\times (k - 1) \\times \\cdots\\times(k - w + 1) Akw=(k)×(k1)××(kw+1)

因为 k ≤ 12 k\\leq12 k12,且 12 ! = 479 , 001 , 600 < 1 0 9 < I N T _ M A X 12!=479,001,600<10^9<INT\\_MAX 12!=479,001,600<109<INT_MAX,因此全程使用int即可。

AC代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main() 
    int n, k, w;
    cin >> n >> k >> w;
    w *= 3;
    if (k < w)   // 如果可挑选种类 < 总顿数
        puts("0");
        return 0;
    
    int ans = 1;
    for (int i = k; i >= k - w + 1; i--)
        ans *= i;
    cout << ans << endl;
    return 0;

拓展:

拓展部分不想看的可以不用看,下面将讲述如果数据范围再小一些如何模拟:

我们可以用一个vector来记录已经模拟的部分的饭的种类。用void check(vector<int> already)来进行模拟。

如果已经模拟了 w w w顿饭了,那么这就是一个合法的模拟,直接 a n s + + ans++ ans++即可。否则就在所有未用到的饭中,任选一个继续模拟。

下面代码只能在更下的数据下通过,可通过版本的代码请移步“AC代码”

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;

int n, k, w;
int ans = 0;

void check(vector<int> already)   // 已经模拟过的饭是already
    if (already.size() == w)   // 如果已经模拟了w顿饭
        ans++;  // 可行方案数+1
        return;
    
    bool cannot[k] = 0;  // 不可以再使用的饭(已经吃过的饭(不可再出现)将会被标记为true)
    for (int t : already)   // 已经吃过的饭
        // assert(t < k);
        cannot[t] = true;  // 不能再吃了
    
    for (int i = 0; i < k; i++)   // 枚举每一种饭
        if (!cannot[i])   // 还没吃过
            vector<int> newVector = already;
            newVector.push_back(i);  // 这顿饭吃i
            check(newVector);  // 继续模拟
        
    


int main() 
    cin >> n >> k >> w;
    // assert(n >= w);
    w *= 3;
    if (k < w) 
        puts("0");
        return 0;
    

    check();  // 从0开始模拟

    cout << ans << endl;
    return 0;

如果题目要求输出每种可行的方案数,那么就可以使用上述代码了。

每周提前更新菁英班周赛题解,点关注,不迷路

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/124850901

以上是关于码蹄集 - MT2013 · 饿饿︕饭饭︕ - 解题思路版本的主要内容,如果未能解决你的问题,请参考以下文章

码蹄集 - MT3111· 赋值

算法竞赛入门码蹄集新手村600题(MT1501-1550)

算法竞赛入门码蹄集新手村600题(MT1401-1450)

算法竞赛入门码蹄集新手村600题(MT1201-1250)

算法竞赛入门码蹄集新手村600题(MT1551-1600)

算法竞赛入门码蹄集新手村600题(MT1351-1400)