• topcoder srm 510 div1


    problem1 link

    令$f(x)$表示[0,x]中答案的个数。那么题目的答案为$f(b)-f(a-1)$

    对于$f(x)$来说,假设$x$有$d$位数字,即$[0,d-1]$,那么可以进行动态规划,令$dp(i,s)$表示已经考虑了$[i,d-1]$位的数字,状态为$s$的方案数。状态需要五种:

    0: 前面都是0

    1: 前面不都是0,前高位数字小于$x$且未出现非4,7的数字

    2: 前面不都是0,前高位数字等于$x$且未出现非4,7的数字
    3: 前面不都是0,前高位数字小于$x$且出现非4,7的数字
    4: 前面不都是0,前高位数字等于$x$且出现非4,7的数字

    problem2 link

    首先,只包含4和7的数字并不多。即便$a=1,b=10^{10}$,这中间的只包含的4,7的数字也只有$2^{1}+2^{2}+...+2^{10}$个。

    假设预计算出这些数字存储在数组$A$中

    那么从贪心的角度看,Join枚举的区间的开始一定是$A_{i}-bLen+1$,而 Brus枚举的区间一定是从$A_{j}+1$开始。

    problem3 link

    设$n$的$B$进制表示为$n=sum_{i=0}^{K}a_{i}B^{i},a_{i}<B$

    首先,当$K$较大时$B$会很小。因此可以分为三类分别计算:

    (1) $K=1$。即$n=a*B+b$。枚举$a,b$,判断$B$是否存在即可。

    (2) $K=2$。即$n=a*B^{2}+b*B+c$。枚举$a,b,c$然后判断是否存在$B$。这里可以进行的一个优化是:假设枚举了$a,b$,那么对于连续枚举的两个c,比如$c_{1},c_{2},c_{1}<c_{2}$来说,假如$a*B_{1}^{2}+b*B_{1}+c_{1}=n,a*B_{2}^{2}+b*B_{2}+c_{2}=n$,那么$B_{1}>B_{2}$。所以如果$a*B_{1}^{2}+b*B_{1}+c_{2}<n $,那么对于$(a,b,c_{2})$来说,必然没有对应的$B$的解

    (3) $K ge 3$。直接枚举$B$,判断得到的$a_{i}$是否都是lucky-number即可。

    (这一道python跑不过,用了Java)

    code for problem1

    class TheAlmostLuckyNumbersDivOne:
    
        def find(self, a, b):
            return self.calculate(b) - self.calculate(a - 1)
    
    
        def calculate(self, a):
            print a
            if a == 0:
                return 1
            d = []
            while a != 0:
                d.append(a % 10)
                a /= 10
            n = len(d)
            f = self.newArray2D(n, 5, 0)
            for i in range(d[n - 1] + 1):
                if i == 0:
                    f[n - 1][0] += 1
                elif i == d[n - 1]:
                    if i == 4 or i == 7:
                        f[n - 1][2] += 1
                    else:
                        f[n - 1][4] += 1
                else:
                    if i == 4 or i == 7:
                        f[n - 1][1] += 1
                    else:
                        f[n - 1][3] += 1
    
            for i in range(n - 2, -1, -1):
                t = d[i]
                for j in range(10):
                    if j == 0:
                        f[i][0] += f[i + 1][0]
                        f[i][3] += f[i + 1][1]
                        if j == t:
                            f[i][4] += f[i + 1][2]
                        elif j < t:
                            f[i][3] += f[i + 1][2]
                    elif j == 4 or j == 7:
                        f[i][1] += f[i + 1][0]
                        f[i][1] += f[i + 1][1]
                        if j == t:
                            f[i][2] += f[i + 1][2]
                            f[i][4] += f[i + 1][4]
                        elif j < t:
                            f[i][1] += f[i + 1][2]
                            f[i][3] += f[i + 1][4]
                        f[i][3] += f[i + 1][3]
    
                    else:
                        f[i][3] += f[i + 1][0]
                        f[i][3] += f[i + 1][1]
                        if j == t:
                            f[i][4] += f[i + 1][2]
                        elif j < t:
                            f[i][3] += f[i + 1][2]
    
            return f[0][0] + f[0][1] + f[0][2] + f[0][3] + f[0][4]
    
        def newArray2D(self, n, m, init):
            f = [0] * n
            for i in range(n):
                f[i] = [init] * m
            return f
    

      

    code for problem2

    class TheLuckyGameDivOne:
    
        f = []
        fLen = 0
        a = 0
        b = 0
        jLen = 0
        bLen = 0
        cache = []
    
        def generateLuckyNumber(self, x):
            if x > self.b:
                return
            if x >= self.a:
                self.f.append(x)
            self.generateLuckyNumber(x * 10 + 4)
            self.generateLuckyNumber(x * 10 + 7)
    
        def binarySearch(self, key):
            if self.f[0] > key:
                return 0
            if self.f[self.fLen - 1] <= key:
                return self.fLen
            low = 0
            high = self.fLen - 1
            maxIndex = 0
            while low <= high:
                mid = (low + high) >> 1
                if self.f[mid] <= key:
                    maxIndex = max(maxIndex, mid)
                    low = mid + 1
                else:
                    high = mid - 1
            return maxIndex + 1
    
    
        def calculate(self, start, end):
            result = self.binarySearch(start + self.bLen - 1) - self.binarySearch(start - 1)
            for i in range(self.fLen):
                bStart = self.f[i] + 1
                bEnd = bStart + self.bLen - 1
                if start <= bStart and bEnd <= end:
                    result = min(result, self.cache[i])
            return result
    
        def init(self):
            self.cache = [0] * self.fLen
    
            for i in range(self.fLen):
                bStart = self.f[i] + 1
                bEnd = bStart + self.bLen - 1
                self.cache[i] = self.binarySearch(bEnd) - self.binarySearch(bStart - 1)
    
        def find(self, a, b, jLen, bLen):
            self.a = a
            self.b = b
            self.jLen = jLen
            self.bLen = bLen
            self.generateLuckyNumber(0)
    
            self.f.sort()
            if len(self.f) == 0:
                return 0
    
            self.fLen = len(self.f)
            self.init()
    
            result = 0
            for i in range(self.fLen + 1):
                start = a
                if i < self.fLen:
                    start = self.f[i] - bLen + 1
                end = start + jLen - 1
                if a <= start and end <= b:
                    result = max(result, self.calculate(start, end))
            return result
    
    
    

      

    code for problem3

    import java.util.*;
    import java.math.*;
    import static java.lang.Math.*;
    
    public class TheLuckyBasesDivOne {
    
    	List<Long> f = new ArrayList<>();
    	long n;
    
    	void generateLuckyNumber(Long x) {
    		if (x > n) {
    			return;
    		}
    		if (x > 0) {
    			f.add(x);
    		}
    		generateLuckyNumber(x * 10 + 4);
    		generateLuckyNumber(x * 10 + 7);
    	}
    
    	static boolean isLucky(Long x) {
    		if (x == 0) {
    			return false;
    		}
    		while (x > 0) {
    			if (x % 10 != 4 && x % 10 != 7) {
    				return false;
    			}
    			x /= 10;
    		}
    		return true;
    	}
    
    	long calculate4() {
    		long result = 0;
    		for (long base = 2;;++ base) {
    			int num = 0;
    			boolean tag = true;
    			long x = n;
    			while (x > 0) {
    				tag = tag && isLucky(x % base);
    				num += 1;
    				x /= base;
    			}
    			if (num <= 3) {
    				break;
    			}
    			if (tag) {
    				result += 1;
    			}
    		}
    		return result;
    	}
    
    
    	long searchMax(long a, long b, long c) {
    		long low = 0;
    		long high = (long)Math.sqrt(n) + 1;
    		long result = 0;
    		while (low <= high) {
    			long mid = (low + high) >> 1;
    			if (a <= n / mid && a * mid <= n / mid && b <= n / mid
    					&& a * mid * mid + b * mid + c <= n) {
    				result = Math.max(result, mid);
    				low = mid + 1;
    			}
    			else {
    				high = mid - 1;
    			}
    		}
    		return result;
    	}
    
    
    	long calculate3() {
    		long result = 0;
    		for (long a : f) {
    			long B0 = a + 1;
    			if (a > n / B0 || a * B0 > n / B0) {
    				break;
    			}
    			for (long b : f) {
    				long B1 = Math.max(B0, b + 1);
    				if (a > n / B1 || a * B1 > n / B1
    						|| b * B1 > n || a * B1 * B1 + b * B1 > n) {
    					break;
    				}
    				long pre = -1;
    				for (long c : f) {
    					long B2 = Math.max(B1, c + 1);
    					if (a > n / B2 || a * B2 > n / B2
    							|| b * B2 > n || a * B2 * B2 + b * B2 + c > n) {
    						break;
    					}
    					if (pre != -1 && a * pre * pre + b * pre + c < n) {
    						continue;
    					}
    					pre = searchMax(a, b, c);
    					if (a * pre * pre + b * pre + c == n) {
    						result += 1;
    					}
    				}
    			}
    		}
    		return result;
    	}
    
    	long calculate2() {
    		long result = 0;
    		for (long a : f) {
    			if (a * (a + 1) > n) {
    				break;
    			}
    			for (long b : f) {
    				long B = Math.max(a, b) + 1;
    				if (a > n / B || a * B + b > n) {
    					break;
    				}
    				long t = n - b;
    				if (t % a == 0 && t / a > a && t / a > b) {
    					result += 1;
    				}
    			}
    		}
    		return result;
    	}
    	public long find(long n) {
    		if (isLucky(n)) {
    			return -1;
    		}
    
    		this.n = n;
    		generateLuckyNumber(0L);
    		Collections.sort(f);
    
    		return calculate2() + calculate3() + calculate4();
    	}
    }
    

      

  • 相关阅读:
    英语老师不想让你知道的一些网站分享
    最近三周开发的桌面应用系统
    UML技术沙龙PPT
    Pandas时间处理的一些小方法
    合并函数总结
    开博宣言
    DBGrid中增加一列CHECKBOX
    关于Delphi的Hint
    操作EXCEL
    关于FastReport
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/7954328.html
Copyright © 2020-2023  润新知