010数论——算法备赛

news2025/7/18 0:41:46

数论

模运算

一般求余都是对正整数的操作,如果对负数,不同编程语言结果可能不同。

C/javapython
a>m,0<=a%m<=m-1 a<m,a%m=a~
5%3==2~
-5%3== -21
(-5)%(-3)== -2~
5%(-3)==2-1
正数:(a+b)%m==((a%m)+(b%m))%m~
正数:(a-b)%m=((a%m)-(b%m))%m~
(a*b)%m=((a%m)*(b%m))%m~
an%m=(a%m)n % m~

C/java:负数求余结果为非正数,正数求余结果为非负数,求余结果的绝对值为两数绝对值求余的结果

python:若余数m为正数,求余结果范围[0,m-1],若余数m为负数,求余结果范围[m+1,0]

乘法取模公式需注意:两个大数a*b可能溢出。

以下代码在一定程度上可以解决

typedef long long ll;
ll mul(ll a,ll b,ll m){
    a%=m;
    b%=m;
    ll res=0;
    while(b>0){  //以空间换时间
        if(b&1) res=(res+a)%m;
        a=(a<<1)%m;  //需保证2a不会溢出 a>m;
        b>>=1;
    }
    return res;
}

为了不直接计算 a*b ,改为计算(a*2)*(b/2)

即为求**(a*2)*(b/2)%m ={((a*2)%m )*(b/2)}%m**。每次将(a*2)%m 赋值给a;

连续执行 a*2和b/2

即(a*2*2…*2)*(b/2/2…/2),

直到b减少为1,原式改为求 (a*2*2…*2)%m

当b减少为0时,循环结束,返回目标值res。

当b为偶数时 a*b ==(a*2)*(b/2)

当b为奇数时 a*b ==(a*2)*(b/2)+a 每次将多出来的a求余存进res。

最大公约数

递归写法

int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}

动态规划写法

while(b > 0){
    int tmp = a % b;
    a = b;
    b = tmp;
}
return a;

最小公倍数

int lcm(int a,int b){
    return a*b/gcd(a,b);
}

快速幂

对于a^n 如果一个一个地乘,计算量为O(n),采用快速幂计算,计算量为O(log2n);

以a^11为例

利用幂次与二进制的关系 a11=a8*a2*a1;

ll fastPow(ll a,ll n){
    ll ans=1;
    while(n){
        if(n&1)  ans*=a;
        a*=a;  //倍增递推 a  a^2  a^4  a^8 ...
        n>>=1;  //右移,把处理过的n的最后一位去掉
    }
    return ans;
}

幂运算的结果往往是大数,一般会对其取模处理。更据模的性质,

an%m=(a%m)n % m.

上述代码修改为

ll fastPow(ll a,ll n,ll m){
    ll ans=1;
    a%=m;  //一定程度上能防止溢出。,但做题时仍需谨慎,a不能太大,否则只能用高精度处理。
    while(n){
        if(n&1) ans=(ans*a)%m;
        a=(a*a)%m;
        n>>=1;
    }
}

上述代码依然存在溢出问题。 ans*a a*a可能溢出

计算 a^n%m ,如果n极大 如 n=10^200000000, 可以用“欧拉降幂”的方法。

统计好数字的数目

问题描述

我们称一个数字字符串是 好数字 当它满足(下标从 0 开始)偶数 下标处的数字为 偶数奇数 下标处的数字为 质数2357)。

  • 比方说,"2582" 是好数字,因为偶数下标处的数字(28)是偶数且奇数下标处的数字(52)为质数。但 "3245" 不是 好数字,因为 3 在偶数下标处但不是偶数。

给你一个整数 n ,请你返回长度为 n 且为好数字的数字字符串 总数 。由于答案可能会很大,请你将它对 109 + 7 取余后返回

一个 数字字符串 是每一位都由 09 组成的字符串,且可能包含前导 0 。

原题链接

代码

int countGoodNumbers(long long n) {
        int mod=1e9+7;
        long long t4=n/2,t5=(n+1)/2;
        auto pows=[&](long long s,long long t)->long long{  //快速幂
            long long ans=1;
            while(t){
                if(t&1) ans=(ans*s)%mod;
                s=(s*s)%mod;
                t>>=1;
            }
            return ans;
        };
        return (pows(4,t4)*pows(5,t5))%mod;
    }

字符串表达式运算

基本计算器|

问题描述

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()

提示:

  • 1 <= s.length <= 3 * 105
  • s 由数字、'+''-''('')'、和 ' ' 组成
  • s 表示一个有效的表达式
  • ‘+’ 不能用作一元运算(例如, “+1” 和 "+(2 + 3)" 无效)
  • ‘-’ 可以用作一元运算(即 “-1” 和 "-(2 + 3)" 是有效的)
  • 输入中不存在两个连续的操作符
  • 每个数字和运行的计算将适合于一个有符号的 32位 整数

原题链接

思路分析

首先考虑如果没有括号的情况,那就是简单的加减运算,有了括号问题就变得复杂一点,借助小学的知识去除括号,那问题就变成简单的加减题。

  • 括号左边运算符为+,那直接去除,例1+(2+3)——>1+2+3
  • 括号左边运算符为-,那去除括号后,括号内的运算符全部反转,例1-(2+3)——>1-2-3

对于嵌套的反转其实就是反转后再反转。

定义oper指示前一个运算符是+(true),还是减-(false)

定义rev指示括号内运算符是否反转,每遍历到一个'('就决定是否对rev取反,遍历到')'就取消决定,这里为应对多重的(),用一个栈来维护前面的决定。

对于oper,rev的值对数值的运算有如下关系:

operrev结果
truetrue-
truefalse+
falsetrue+
falsefalse-

可以看到,oper与rev的共同作用对加还是减运算其实是异或的结果,oper^revtrue,则做加法,oper^revfalse,则做减法。

代码

int calculate(string s) {
    int n = s.size();
    int ans = 0, pre = 0;
    bool oper = true, rev = false;
    stack<bool>st;
    for (int i = 0; i < n; i++) {
        if (s[i] == ' ') continue;
        switch (s[i]) {
        case '+':
            oper = true;
            break;
        case '-':
            oper = false;
            break;
        case '(':
            st.push(oper);
            if (!oper) rev = !rev,oper=true;
            break;
        case ')':
            if (!st.top()) rev = !rev;
            st.pop();
            break;
        default:
            pre=pre*10+(s[i]-'0');
            if(i==n-1||s[i+1]<'0'||s[i+1]>'9'){
                if (rev ^ oper) ans += pre;
                else ans -= pre;
                pre=0;
            }
        }
    }
    return ans;
}
基本计算器||

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

**注意:**不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()

提示:

  • 1 <= s.length <= 3 * 105
  • s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开
  • s 表示一个 有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1]
  • 题目数据保证答案是一个 32-bit 整数

原题链接

代码

int calculate(string s) {
        int ans=0,pre=0,num=0,n=s.size();
        char preOper='+';
        bool isAdd=true;
        for(int i=0;i<=n;i++){
            if(i<n&&s[i]==' ') continue;
            if(i<n&&s[i]>='0'&&s[i]<='9'){
                num=10*num+(s[i]-'0');
            }else{
                switch(preOper){
                    case '*':
                        pre*=num;
                    break;
                    case '/': 
                        pre/=num;
                    break;
                    case '+':
                    case '-':
                        ans+=isAdd?pre:-pre;
                        pre=num;
                        isAdd=preOper=='+';
                    break;
                }
                if(i<n) preOper=s[i];
                num=0;
            }
        }
        ans+=isAdd?pre:-pre;
        return ans;
    }

数位统计

无理数位数查询

问题描述

在这里插入图片描述
原题链接

思路分析

见注释。

代码

#include <bits/stdc++.h>
#define IOSCC ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
typedef unsigned long long ll;
const int N = 1e6 + 10;

ll qpow(ll a,ll b){  //快速幂求a的b次方。
    ll res = 1;
    while(b){
        if(b & 1) res = res * a;
        b >>= 1;
        a = a * a;
    }
    return res;
}

void solve() {
    ll n, m;
    cin >> n >> m; 
    ll res = 0;
    ll i, j;
    for (i = m - 1, j = 1;; i *= m, j++) { //这一步是为了找到在位数为j时可以找到n的位数
        res += i * j;
        if (res >= n) {
            res -= i * j;
            break;  //直接退出,j不再加1、
        }
    }

    ll offset = n - res;  //得到从位数为j开始时的偏移量

    ll num = offset / j;  //target为j位数中的第num个。
    ll digit = offset % j;   //目标数字(数位)为目标数值中的第digit个数字
    if(digit == 0) num--,digit = j; //如果digit为0的话,说明要找的数是数值的最后一位

    ll target = qpow(m, j - 1) + num; //得到当前的数字

    string t1;  //数值可能很大,要用字符串储存。
    while (target) {
        t1 += ('0' + (target % m)); //用字符串存储m进制数target,从低位到高位
        target /= m;
    }
    reverse(t1.begin(), t1.end()); //翻转  将数值target用字符串表示出来(从高位到第位)。
    cout << t1[digit - 1];  //输出位数,因为字符串从0开始,所以减1
}

int main() {
    IOSCC;
    int _ = 1;
    cin >> _;

    while (_--) {
        solve();
        cout << endl;
    }

    return 0;
}
统计强大整数的数目

问题描述

给你三个整数 startfinishlimit 。同时给你一个下标从 0 开始的字符串 s ,表示一个 整数。

如果一个 整数 x 末尾部分是 s (换句话说,sx后缀),且 x 中的每个数位至多是 limit ,那么我们称 x强大的

请你返回区间 [start..finish] 内强大整数的 总数目

如果一个字符串 xy 中某个下标开始(包括 0 ),到下标为 y.length - 1 结束的子字符串,那么我们称 xy 的一个后缀。比方说,255125 的一个后缀,但不是 512 的后缀。

原题链接

代码

long long numberOfPowerfulInt(long long start, long long finish, int limit, string s) {
    long long num=0,digs=1;  num为s表示的数值,digs=10^n(n为num的位数)
    for(int i=0;i<s.size();i++){
        num=num*10+s[i]-'0';
        digs*=10;  
    }
    auto numbers=[&](long long st)->long long{  //求[0,st]范围内的强大整数数目
        long long st_dig=st/digs,st_mod=st%digs,ans=0;
        long long power=1;
        int i=0;
        while(st_dig){
            int p=st_dig%10;
            if(p<=limit){
                ans+=p*power;  
                //最高位为p时,后面有些值可能取不到,组合总数继承上一个ans
                //最高位为[0,p-1]时,后面每位可取[0,limits],组合总数为p*power
                //总的组合数就是ans+p*power.
                if(!i&&st_mod>=num) ans++;  //第一位且st_mod>=num时,少算了一个,加上.
            }
            else{
                 ans=(limit+1)*power;
            }
            st_dig/=10;
            power*=limit+1; 
            i++;
        }
        if(st>=num&&ans==0) return 1;  //未进入循环,但st>=num,可以构成一个强大整数
        return ans;
    };
    return numbers(finish)-numbers(start-1);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2337964.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NAT、代理服务、内网穿透

NAT、代理服务、内网穿透 1、NAT1.1、NAT过程1.2、NAPT2、内网穿透3、内网打洞3、代理服务器3.1、正向代理3.2、反向代理1、NAT 1.1、NAT过程 之前我们讨论了IPv4协议中IP地址数量不充足的问题。NAT技术是当前解决IP地址不够用的主要手段,是路由器的一个重要功能。 NAT能够将…

【unity实战】Unity动画层级(Animation Layer)的Sync同步和Timing定时参数使用介绍,同步动画层制作角色的受伤状态

文章目录 前言方案一&#xff1a;复制粘贴原有层级的状态机1、实现2、问题 方法二&#xff1a;勾选Sync同步动画层1、简单实现同步2、同步blend tree的问题3、动画状态的播放时长4、下层状态覆盖了上层状态 专栏推荐完结 前言 如何制作角色的受伤状态&#xff1f; 玩家角色在…

Uniapp调用native.js使用经典蓝牙串口通讯方法及问题解决

本人尝试在uniapp环境下开发一款安卓应用&#xff0c;需要与使用经典蓝牙协议的设备进行串口通讯&#xff0c;而uniapp官方给出的蓝牙操作接口目前只支持BLE&#xff08;低功耗蓝牙&#xff09;&#xff0c;用该接口无法正常获取到我想要连接的设备。 通过大量搜索&#xff0c…

C++23 新特性:行拼接前去除空白符 (P2223R2)

文章目录 1\. 什么是行拼接前去除空白符2\. 为什么需要这一特性3\. 示例代码输出结果 4\. 编译器支持5\. 优势与应用场景5.1 提高代码可读性5.2 减少潜在错误5.3 适用于多行字符串 6\. 其他相关特性7\. 总结 C 语言一直在不断进化&#xff0c;以满足现代软件开发的需求。C23 标…

【通过Zadig给鼠标适配器安装驱动后,鼠标动不了,无法恢复的解决办法】

【通过Zadig给鼠标适配器安装驱动后,鼠标动不了,无法恢复的解决办法 问题产生缘由感谢这位大佬提供的解决办法解决办法 问题产生缘由 通过Zadig给鼠标适配器安装USB GAMING MOUSE这个驱动后,鼠标动不了,无法恢复(重启电脑,卸载鼠标驱动再重装也不可以), 不过还好,我用的是笔记…

GoogleCodeUtil.java

Google动态验证码实现 GoogleCodeUtil.java package zwf;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.SecureRandom;/** https://mvnrepository.com/artifact/commons-codec/…

Maven 简介(图文)

Maven 简介 Maven 是一个Java 项目管理和构建的工具。可以定义项目结构、项目依赖&#xff0c;并使用统一的方式进行自动化构建&#xff0c;是Java 项目不可缺少的工具。 Maven 的作用 提供标准化的项目结构&#xff1a;以前不同的开发工具创建的项目结构是不一样的&#xf…

2025Github介绍与注册(有图片讲解,保姆级)

为什么要注册Github账号 利于团队协作&#xff0c;特别是打比赛的队友 版本控制强大&#xff0c;代码安全 开源项目多&#xff0c;方便个人模仿或抄袭 方便托管&#xff0c;形成自动化工具链 教育福利&#xff0c;教育参与者暂时免费 讲解完了优势&#xff0c;下面讲注册 Gith…

RUI电视桌面中文版:下载安装教程及桌面固件包获取全攻略

在智能电视的使用过程中&#xff0c;一款出色的桌面系统能极大提升用户体验&#xff0c;RUI电视桌面中文版就是这样一个不错的选择。下面为大家详细介绍RUI电视桌面中文版的下载安装教程以及桌面固件包的获取方法。 一、桌面固件包获取 首先是获取桌面固件包。可以通过RUI官方…

OpenAI 34页最佳构建Agent实践

penAI发布O4&#xff0c;也发布34页最佳构建Agent实践&#xff0c;值得阅读。 什么是Agent&#xff1f; 传统软件使用户能够简化和自动化工作流程&#xff0c;而代理能够以高度独立的方式代表用户执行相同的工作流程。 代理是能够独立地代表您完成任务的系统。 工作流程是必…

HOOPS Exchange 与HOOPS Communicator集成:打造工业3D可视化新标杆!

一、概述 在工业3D开发、BIM建筑、数字孪生和仿真分析等高端应用场景中&#xff0c;数据格式复杂、模型体量庞大、实时交互体验要求高&#xff0c;一直是困扰开发者的难题。Tech Soft 3D旗下的HOOPS Exchange和HOOPS Communicator&#xff0c;正是解决这类问题的黄金搭档。二者…

C#进阶学习(六)单向链表和双向链表,循环链表(下)循环链表

目录 &#x1f4ca; 链表三剑客&#xff1a;特性全景对比表 一、循环链表节点类 二、循环链表的整体设计框架 三、循环列表中的重要方法&#xff1a; &#xff08;1&#xff09;头插法&#xff0c;在头结点前面插入新的节点 &#xff08;2&#xff09;尾插法实现插入元素…

Unity使用Newtonsoft.Json本地化存档

我是标题 1.依赖包2.原理&#xff1a;3.代码4.可用优化5.数据加密 1.依赖包 Newtonsoft请在PacakgeManager处下载。 参考&#xff1a;打工人小棋 2.原理&#xff1a; 把要存储的对象数据等使用JsonConvert.SerializeObject(object T)进行序列化为字符串&#xff0c;并且通过…

2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(六级)真题

青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;六级&#xff09; 分数&#xff1a;100 题数&#xff1a;38 答案解析&#xff1a;https://blog.csdn.net/qq_33897084/article/details/147341458 一、单选题(共25题&#xff0c;共50分) 1. 在tkinter的…

Python 浮点数运算之谜:深入解析round(0.675, 2)等输出异常

一、问题背景&#xff1a;当浮点数运算遇见 “反直觉” 结果 在 Python 开发中&#xff0c;以下代码输出常让开发者困惑&#xff1a; print(round(0.675, 2)) # 预期0.67&#xff0c;实际0.68||预期0.68&#xff0c;实际0.67 print(0.1 0.2) # 预期0.3&…

【C#】Html转Pdf,Spire和iTextSharp结合,.net framework 4.8

&#x1f339;欢迎来到《小5讲堂》&#x1f339; &#x1f339;这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。&#x1f339; &#x1f339;温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01;&#…

极狐GitLab 注册限制如何设置?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 注册限制 (BASIC SELF) 您可以对注册实施以下限制&#xff1a; 禁用新注册。新注册需要管理员批准。需要用户电子邮件确认。…

利用大模型实现地理领域文档中英文自动化翻译

一、 背景描述 在跨国性企业日常经营过程中&#xff0c;经常会遇到专业性较强的文档翻译的需求&#xff0c;例如法律文书、商务合同、技术文档等&#xff1b;以往遇到此类场景&#xff0c;企业内部往往需要指派专人投入数小时甚至数天来整理和翻译&#xff0c;效率低下&#x…

SGFormer:卫星-地面融合 3D 语义场景补全

论文介绍 题目&#xff1a;SGFormer: Satellite-Ground Fusion for 3D Semantic Scene Completion 会议&#xff1a;IEEE / CVF Computer Vision and Pattern Recognition Conference 论文&#xff1a;https://www.arxiv.org/abs/2503.16825 代码&#xff1a;https://githu…

Trinity三位一体开源程序是可解释的 AI 分析工具和 3D 可视化

一、软件介绍 文末提供源码和程序下载学习 Trinity三位一体开源程序是可解释的 AI 分析工具和 3D 可视化。Trinity 提供性能分析和 XAI 工具&#xff0c;非常适合深度学习系统或其他执行复杂分类或解码的模型。 二、软件作用和特征 Trinity 通过结合具有超维感知能力的不同交…