cf997B

 

 

题解: 首先我们转化下思维,题目上说用1 5 10 50 ,我们选择用0 4 9 49,这样我们只需要去考虑序列中4 9 49 的个数就可以了 

这道题的难点在于一个数可能会有多种表示方法,为了避免重复,我们表示每一个数的时候应该用唯一的方式去表示他

因此对于一个数,我们先尽量去用49凑,再用9去凑,然后再用4

这样任何一个能拼凑出来的数都可以用这种方式表示出来并且是唯一的

因此我们可以枚举4,9,49的数量,在满足数量不超过n的前提下,判定他表示的这个数是不是我们要的那种表示方法(防止重复)

如何判定:举个例子:如果4的数量超过了9个,那么这个一定是重复的,因为9 个 4 可以用 4 个 9 来替代,我们的表示方法要求尽量先去用9,因此这种表示重复

也就是说,如果一些比较小的数的和可以用一些比较大的数凑出来,那么这种表示就是重复的

另外我们可以发现49不可能被替代,只有4 或者 9 太多,会导致被49所替代

然后容易发现4 , 9 的数量不会超过 50 个

因此枚举 4 和 9 的数量 ,然后判断是否会重复,如果不会重复,那么答案就可以加上n-num4-num9,因为剩下的位置9可以随意的填

代码是别人的,看了他代码才彻底懂了这个题

// Written by Sayutin Dmitry

#include <bits/stdc++.h>

using namespace std;

template <typename T>
T input() {
    T res;
    cin >> res;
    return res;
}

#define ALL(A) A.begin(), A.end()
#define SZ(A) int(A.size())

int main() {
    std::iostream::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    int n = input<int>();

    const int max_go = 49;

    bool good[max_go + 1][max_go + 1];
    for (int i = 0; i <= max_go; ++i)
        for (int j = 0; j <= max_go; ++j)
            good[i][j] = 1;

    for (int i = 0; i <= max_go; ++i)
        for (int j = 0; j <= max_go; ++j)
            for (int iprime = 0; iprime <= max_go; ++iprime)
                for (int jprime = 0; jprime <= max_go; ++jprime)
                    if (4 * iprime + 9 * jprime < 4 * i + 9 * j and (4 * i + 9 * j) % 49 == (4 * iprime + 9 * jprime) % 49)
                        good[i][j] = 0;

    int64_t ans = 0;
    for (int num4 = 0; num4 <= n and num4 <= max_go and num4 < 9; ++num4)
        for (int num9 = 0; num9 + num4 <= n and num9 <= max_go; ++num9)
            if (good[num4][num9])
                ans += (n - num9 - num4 + 1);

    cout << ans << "\n";
    
    return 0;
}

  

posted on 2020-03-02 19:07  欣崽  阅读(260)  评论(0编辑  收藏  举报

导航