zoukankan      html  css  js  c++  java
  • 洛谷 P6218

    题目链接: P6218 [USACO06NOV] Round Numbers S

    题目大意

    详见题目

    solution

    有一个显而易见的结论

    发现 (ans_{l, r} = ans_{1. r} - ans_{1, l - 1})

    那只需要处理 (1 - r) 的即可

    (f_{i, j, k}) 表示长度为 (i) 最高位为 (j) 的且 (1) 的个数为 (k) 的数的个数

    1. (j=1, f_{i, j, k} = sumlimits_{p = 0}^{p leqslant 1}sumlimits_{k = 0}^{k leqslant i} f_{i - 1, p, k - 1})
    2. (j=0, f_{i, j, k} = sumlimits_{p = 0}^{p leqslant 1}sumlimits_{k = 0}^{k leqslant i} f_{i - 1, p, k})

    对于(ans_{1, r}) 我们可以采用以下策略 :

    (len)(r) 的位数, (a_{len})(r) 的每一位

    1. 对于首位为 (1) 且前面有 (cnt1)(1)(f) , (res += f_{i, 0, j}, i in [1, len), j in [0, len / 2 - cnt1])
    2. 对于首位为 (0)(f) , (res += f_{i, 1, j}, i in [1, len), j in [0, i / 2])

    那么答案就是 (ans_{1, r} - ans_{1, l - 1})

    Code:

    /**
    *    Author: Aliemo
    *    Data: 
    *    Problem: 
    *    Time: O()
    */
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    #define ll long long
    #define rr register
    
    #define inf 1e9
    #define MAXN 100010
    
    using namespace std;
    
    inline int read() {
    	int s = 0, f = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void print(int x) {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + 48);
    }
    
    int l, r, len;
    
    int f[50][2][50], a[50];
    
    inline void init() {
    	f[1][1][1] = 1, f[1][0][0] = 1;
    	for (rr int i = 2; i < 35; i++) 
    		for (rr int j  = 0; j <= 1; j++) 
    			for (rr int k = 0; k <= i; k++)
    				for (rr int p = 0; p <= 1; p++) 
    					if (!j) f[i][j][k] += f[i - 1][p][k];
    					else if (k) f[i][j][k] += f[i - 1][p][k - 1];
    }
    
    inline int solve(int x) {
    	memset(a, 0, sizeof a);
    	len = 0;
    	while (x) {
    		a[++len] = x % 2;
    		x /= 2;
    	}
    	int ans = 0, cnt1 = 1, cnt0 = 0;
    	for (rr int i = len - 1; i >= 1; i--) {
    		int x = a[i];
    		if (x) {
    			for (rr int j = 0; j <= len / 2 - cnt1; j++) {
    				ans += f[i][0][j];
    				// cout << ans << "
    ";
    			}
    		}
    		cnt1 += x;
    		cnt0 += (x == 0);
    		if (cnt0 >= cnt1 && i == 1) ans++;
    	}
    	for (rr int i = 1; i < len; i++)
    		for (rr int j = 0; j <= i / 2; j++)
    			ans += f[i][1][j];
    	return ans;
    }
    
    signed main() {
    	init();
    	l = read(), r = read();
    	cout << solve(r) - solve(l - 1);
    }
    
  • 相关阅读:
    图灵2010.05书讯
    上海.NET技术交流会
    图灵2010.07书讯
    高效模式编写者的7个习惯
    QRCode 二维码开源DLL
    javascript 复习
    关于反射技术
    数字签名与加密解密
    使用负载均衡技术建设高负载的网络站点
    dreamweaver cs5.5中的phonegap升级测试
  • 原文地址:https://www.cnblogs.com/lieberdq/p/13992302.html
Copyright © 2011-2022 走看看