【数位】【数论】【分类讨论】2999. 统计强大整数的数目

2024-02-26 19:20

本文主要是介绍【数位】【数论】【分类讨论】2999. 统计强大整数的数目,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者推荐

动态规划的时间复杂度优化

本文涉及知识点

数位 数论

LeetCode2999. 统计强大整数的数目

给你三个整数 start ,finish 和 limit 。同时给你一个下标从 0 开始的字符串 s ,表示一个 正 整数。
如果一个 正 整数 x 末尾部分是 s (换句话说,s 是 x 的 后缀),且 x 中的每个数位至多是 limit ,那么我们称 x 是 强大的 。
请你返回区间 [start…finish] 内强大整数的 总数目 。
如果一个字符串 x 是 y 中某个下标开始(包括 0 ),到下标为 y.length - 1 结束的子字符串,那么我们称 x 是 y 的一个后缀。比方说,25 是 5125 的一个后缀,但不是 512 的后缀。
示例 1:
输入:start = 1, finish = 6000, limit = 4, s = “124”
输出:5
解释:区间 [1…6000] 内的强大数字为 124 ,1124 ,2124 ,3124 和 4124 。这些整数的各个数位都 <= 4 且 “124” 是它们的后缀。注意 5124 不是强大整数,因为第一个数位 5 大于 4 。
这个区间内总共只有这 5 个强大整数。
示例 2:
输入:start = 15, finish = 215, limit = 6, s = “10”
输出:2
解释:区间 [15…215] 内的强大整数为 110 和 210 。这些整数的各个数位都 <= 6 且 “10” 是它们的后缀。
这个区间总共只有这 2 个强大整数。
示例 3:
输入:start = 1000, finish = 2000, limit = 4, s = “3000”
输出:0
解释:区间 [1000…2000] 内的整数都小于 3000 ,所以 “3000” 不可能是这个区间内任何整数的后缀。
提示:
1 <= start <= finish <= 1015
1 <= limit <= 9
1 <= s.length <= floor(log10(finish)) + 1
s 数位中每个数字都小于等于 limit 。
s 不包含任何前导 0 。

数论

len1 = s.length s1 = 下届.right(len1) s2 = 上届.right(len1)
枚举合法数字的长度len2。
我们当前数字假定除掉作为后缀的s,余下的部分为x,x的len = len2- len1。统计x的可能数量。难点:上下界可能包括limit以外的数字。
分类讨论:
一,x就是下界的前缀。
二,x就是上界的前缀。
三,x同时是上下界的前缀,做特殊处理,此时情况四不会存在。return (s1<=s)&&(s <= s2);
四,x 在上下界前缀之间。
处理余下的三种情况:
一,下界的前缀不包括limit及以上数字且s1 <= s,数量+1。
二,上界的前缀不包括limit及以上数字且s <= s2,数量+1。
三,小于上界前缀的数量-小于下界前缀的数量-等于下届前缀的数量。加上s后,一定在上下界之间。
等于下届前缀的数量:如果下届前缀不包括limit及以上数字,为1;否则为0。
小于下界(上界)前缀t的数量:
小于t的数量必定有j位前缀相同,j ∈ [ 0 , l e n ) \in[0,len) [0,len) 枚举j。
bitMin = (0==j)?1:0 最高位不能是0,其它位可以为0。
∑ j : 0 l e n − 1 ( m i n ( t [ j ] , l i m i t + 1 ) − b i t M i n ) × ( l i m i t + 1 ) l e n − j − 1 \sum_{j:0}^{len-1}(min(t[j],limit+1)-bitMin)\times (limit+1)^{len-j-1} j:0len1(min(t[j],limit+1)bitMin)×(limit+1)lenj1
就是当前位的取值数量 乘以 后面各位的取值数量。如果s[j]>=limit,则不会存在(j+1)位及更多位前缀相等。提前退出循环。

代码

核心代码

class Solution {
public:long long numberOfPowerfulInt(long long start, long long finish, int limit, string s) {m_s = s;m_limit = limit;const string strLow = std::to_string(start);const string strUp = std::to_string(finish);const int len0 = strLow.length();const int len = strUp.length();		m_vUnit.emplace_back(1);for (int i = 1; i <= 15; i++){m_vUnit.emplace_back(m_vUnit.back() * (limit+1));}if (len0 == len){return Do(strLow, strUp);}long long llRet = 0;llRet += Do(strLow, string(len0, limit+ '0'));for (int i = len0+1; i < len; i++){llRet += Do(("1" + string(i - 1, '0')).c_str(), string(i, limit + '0').c_str());}	llRet +=Do (("1" + string(len - 1, '0')).c_str(), strUp.c_str());return llRet;}long long Do(string strLow, string strUp){const int len = strLow.length() - m_s.length();if (len < 0 ){return 0;}auto [llCnt1, bVilid1] = LessEqual(len, strLow);auto [llCnt2, bVilid2] = LessEqual(len, strUp);bool b1 = (strLow.substr(len) <= m_s) && (bVilid1);bool b2 = (strUp.substr(len) >= m_s) && (bVilid2);if (strLow.substr(0,len) == strUp.substr(0,len)){return b1 && b2;}return (llCnt2 - llCnt1 - (bVilid1&&len)) + b1 + b2;}std::pair<long long, bool> LessEqual(int len,const string& s ){bool bVilid = true;long long llCnt = 0;for (int i = 0; i < len; i++){//计算小于数量const int bitMin = (0 == i) ? 1 : 0;if (bVilid){llCnt += (min(s[i] - '0', m_limit + 1) - bitMin) * m_vUnit[len - i - 1];}if (s[i] > m_limit + '0'){bVilid = false;}		}return make_pair(llCnt, bVilid);}vector<long long> m_vUnit;string m_s;int m_limit;
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{long long start, finish;int limit;string s;{Solution sln;start = 1, finish = 1000000000000000, limit = 5, s = "1000000000000000";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(1, res);}{Solution sln;start = 1829505, finish = 1955574, limit = 7, s = "11223";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(0, res);}{Solution sln;start = 5398, finish = 6415, limit = 8, s = "101";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(1, res);}{Solution sln;start = 1, finish = 6000, limit = 4, s = "124";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(5, res);}{Solution sln;start = 15, finish = 215, limit = 6, s = "10";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(2, res);}{Solution sln;start = 10, finish = 1844, limit = 5, s = "12";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(12, res);}{Solution sln;start = 1, finish = 2000, limit = 8, s = "1";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(162, res);}{Solution sln;start = 1829505, finish = 1255574165, limit =7, s = "11223";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(5470, res);}{Solution sln;start = 15398, finish = 1424153842, limit = 8, s = "101";auto res = sln.numberOfPowerfulInt(start, finish, limit, s);Assert(783790, res);}}

优化

n位数,可以看成包括(m-n)个前置0的m位数。

class Solution {
public:long long numberOfPowerfulInt(long long start, long long finish, int limit, string s) {m_s = s;m_limit = limit;string strLow = std::to_string(start);const string strUp = std::to_string(finish);if (strLow.length() < strUp.length()){strLow = string(strUp.length() - strLow.length(), '0')+strLow;}		m_vUnit.emplace_back(1);for (int i = 1; i <= 15; i++){m_vUnit.emplace_back(m_vUnit.back() * (limit+1));}return Do(strLow, strUp);}long long Do(string strLow, string strUp){const int len = strLow.length() - m_s.length();if (len < 0 ){return 0;}auto [llCnt1, bVilid1] = LessEqual(len, strLow);auto [llCnt2, bVilid2] = LessEqual(len, strUp);bool b1 = (strLow.substr(len) <= m_s) && (bVilid1);bool b2 = (strUp.substr(len) >= m_s) && (bVilid2);if (strLow.substr(0,len) == strUp.substr(0,len)){return b1 && b2;}return (llCnt2 - llCnt1 - (bVilid1&&len)) + b1 + b2;}std::pair<long long, bool> LessEqual(int len,const string& s ){bool bVilid = true;long long llCnt = 0;for (int i = 0; i < len; i++){//计算小于数量if (bVilid){llCnt += (min(s[i] - '0', m_limit + 1) - 0) * m_vUnit[len - i - 1];}if (s[i] > m_limit + '0'){bVilid = false;}		}return make_pair(llCnt, bVilid);}vector<long long> m_vUnit;string m_s;int m_limit;
};

这篇关于【数位】【数论】【分类讨论】2999. 统计强大整数的数目的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/749888

相关文章

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

PTA求一批整数中出现最多的个位数字

作者 徐镜春 单位 浙江大学 给定一批整数,分析每个整数的每一位数字,求出现次数最多的个位数字。例如给定3个整数1234、2345、3456,其中出现最多次数的数字是3和4,均出现了3次。 输入格式: 输入在第1行中给出正整数N(≤1000),在第二行中给出N个不超过整型范围的非负整数,数字间以空格分隔。 输出格式: 在一行中按格式“M: n1 n2 ...”输出,其中M是最大次数,n

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

整数Hash散列总结

方法:    step1  :线性探测  step2 散列   当 h(k)位置已经存储有元素的时候,依次探查(h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中,S为 数组长度。 HDU 1496   a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 。 x在 [-100,100] 解的个数  const int MaxN = 3000

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

hdu4267区间统计

题意:给一些数,有两种操作,一种是在[a,b] 区间内,对(i - a)% k == 0 的加value,另一种操作是询问某个位置的值。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import

hdu4417区间统计

给你一个数列{An},然后有m次查询,每次查询一段区间 [l,r] <= h 的值的个数。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamRead