zoukankan      html  css  js  c++  java
  • LibreOJ 10163 Amount of Degrees

    题目链接:LibreOJ 10163 Amount of Degrees

    题目大意:

    题解:
    主要思想是进制转换。
    一个数(x)转换为(b)进制可以表示为(x = a_0b^0 + a_1b^1 + a_2b^2 + ...),题目要求的就是系数(a_0,a_1,a_2,...)中有(k)(1),其余是(0)的情况的个数。
    于是我们将(a_0,a_1,a_2,...)排成一个序列(a_0a_1a_2...),题目就转变成求满足有(k)(1)(01)序列的个数。
    (dp[i][j])表示(i)(01)序列中(1)的个数为(j)的序列个数,则状态转移方程为:(dp[i][j]=dp[i-1][j-1]+dp[i-1][j])
    预处理出序列个数之后,将数(x)转换成(a_0a_1a_2...)系数序列,求字典序小于等于它的系数序列且(1)的个数不超过(k)(01)序列个数,即为([0,x])区间内恰好等于(k)个互不相等的(b)的整数次幂之和的数的个数,记作(count(x)),则答案为(count(y)-count(x-1))

    #include <iostream>
    using namespace std;
    
    #define N 1010
    
    int dp[35][35], x, y, k, b;
    
    void init() {
        dp[0][0] = 1;
        for (int i = 1; i <= 31; ++i) {
            dp[i][0] = 1;
            for (int j = 1; j <= i; ++j) {
                dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
            }
        }
    }
    
    int count(int x) {
        int num[35], cnt = 0;
        while (x) {
            num[++cnt] = x % b;
            x /= b;
        }
        int ans = 0, tot = 0;
        for (int i = cnt; i >= 1; --i) {
            if (num[i] == 1) {
                ans += dp[i - 1][k - tot];
                if (++tot > k) {
                    break;
                }
            } else if (num[i] > 1) {
                return ans += dp[i][k - tot];
            }
        }
        return tot == k ? ++ans : ans;
    }
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
        init();
        cin >> x >> y >> k >> b;
        cout << count(y) - count(x - 1);
        return 0;
    }
    
  • 相关阅读:
    每天一道算法题(13)——使用递归颠倒栈
    每天一道算法题(12)——和为n的连续正数序列或者随机数
    函数模板
    答题总结(1)
    顶点间最短路径长度之探寻算法
    最小生成树
    new与delete,malloc与free
    C++的继承与接口
    笔记13 AOP中After和AfterReturning的区别
    笔记12 注入AspectJ切面
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/15068629.html
Copyright © 2011-2022 走看看