• 模板


    二进制的某道题。

    int a[40];
    ll dp[40][40][40];
    ll dfs(int pos, int s1, int s2, bool lead, bool limit) {
        if(pos == -1) {
            if(s1 >= s2)
                return 1;
            else
                return 0;
        }
        if(!limit && !lead && dp[pos][s1][s2] != -1)
            return dp[pos][s1][s2];
        int up = limit ? a[pos] : 1;
        ll ans = 0;
        for(int i = 0; i <= up; i++) {
            int ns1 = s1 + ((!lead) && i == 0);
            int ns2 = s2 + (i == 1);
            ans += dfs(pos - 1, ns1, ns2, lead && i == 0, limit && i == a[pos]);
        }
        if(!limit && !lead)
            dp[pos][s1][s2] = ans;
        return ans;
    }
    
    ll solve(ll x) {
        if(x < 0)
            return 0;
        int pos = 0;
        while(x) {
            a[pos++] = x % 2;
            x /= 2;
        }
        return dfs(pos - 1, 0, 0, true, true);
    }
    
    void test_case() {
        memset(dp, -1, sizeof(dp));
        ll L, R;
        scanf("%lld%lld", &L, &R);
        printf("%lld
    ", solve(R) - solve(L - 1));
    }
    

    十进制的某道题,统计[L,R]中,[0,9]的数字的出现次数,这个需要注意很多细节。比如当lead标记存在时不计算0(即使就是0也不计算)。当limit标记存在且i=d[pos]时,说明这一位取i=d[pos]之后,剩下的数字有r[pos-1]+1种,其中数组r表示原数字模10的幂次的余数(也就是十进制下的低位的数,例如:123456,当取到123???时,???的范围就是[000,456],此时对应的r值就是456,当取到122???时,解除了限制,???的范围就是[000,999])。

    int k;
    ll p10[17];
    
    int d[17];
    ll r[17];
    ll dp[17];
    
    ll dfs(int pos, bool lead, bool limit) {
        if(pos == 0)
            return 0;
        if(!lead && !limit && dp[pos] != -1)
            return dp[pos];
        int up = limit ? d[pos] : 9;
        ll ans = 0;
        for(int i = 0; i <= up; i++) {
            ll D = dfs(pos - 1, lead && i == 0, limit && i == d[pos]);
            ans += D;
            if(i == k) {
                if(lead && i == 0)
                    continue;
                if(limit && i == d[pos])
                    ans += r[pos - 1] + 1;
                else
                    ans += p10[pos - 1];
            }
        }
        if(!lead && !limit)
            dp[pos] = ans;
        return ans;
    }
    
    ll solve(ll x) {
        if(x < 0)
            return 0;
        int pos = 0;
        ll cx = x;
        while(cx) {
            d[++pos] = cx % 10;
            cx /= 10;
        }
        for(int i = 1; i <= pos; ++i)
            r[i] = x % p10[i];
        return dfs(pos, true, true);
    }
    
    int cost[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
    
    void test_case() {
        p10[0] = 1;
        for(int i = 1; i < 17; ++i)
            p10[i] = p10[i - 1] * 10;
        ll L, R;
        scanf("%lld%lld", &L, &R);
        ll sum = 0;
        for(k = 0; k <= 9; ++k) {
            memset(dp, -1, sizeof(dp));
            ll cnt = solve(R) - solve(L - 1);
            sum += cnt * cost[k];
        }
        printf("%lld
    ", sum);
    }
    
  • 相关阅读:
    微软面试题_中文字符串转换为数字
    微软面试题_3个字母的组合
    LeetCode Notes_#1031_两个非重叠子数组的最大和
    剑指Offer_#57-II_和为 s 的连续正数序列
    LeetCode Notes_#560 和为k的子数组
    LeetCode Notes_#84 柱状图中最大的矩形
    LeetCode Notes_#221 最大正方形
    LeetCode Notes_#146 LRU缓存机制
    码云团队开发项目拉取与推送
    vue父子组件的双向绑定
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12486182.html
Copyright © 2020-2023  润新知