一名提高选手的数论之路(二)

2024-02-05 15:32
文章标签 数论 提高 一名 选手

本文主要是介绍一名提高选手的数论之路(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.乘法逆元(inv)两种求法:
First:(满足p为质数且a与p互质才可以使用)
根据费马小定理: apa(modp)
可得 ap2a1(modp)
由此可知, ap2modp 即是a在模p意义下的逆元
然而 ap2 可以轻易用快速幂算出
Second:(无条件)
通过扩展欧几里得算法来求: exgcd(a,p,x,y)
如此调用,x便是求得的a在模p意义下的逆元
不要问我为什么,我不想(zhi)说(dao)
记得答案是这样的(x+p)%p,因为要防止求出负数
代码就不用了吧。


2.在 O(n) 内求前n个逆元:
这是偶然从一个人的博客里看见的。
首先inv[1]=1
然后inv[i]=(M-M/i)*inv[M%i]%M
如此从2一直递推到n就可以了。
具体证明可以看出处
代码很简单:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
int n,M;
int inv[100001];
int main(){scanf("%d %d",&n,&M);inv[1]=1;for(int i=2;i<=n;i++){inv[i]=(M-M/i)*inv[M%i]%M;}for(int i=1;i<=n;i++){printf("%d ",inv[i]);}return 0;
}

3.Lucas定理:(注意,在算阶乘数组的时候,必须从a[0]开始初始化,不然有可能错。)
这个定理是用来求大组合数取模的结果的。
具体证明呀什么的可以自己百度。
我这里给个公式:
C(n,m)=C(n%p,m%p)*C(n/p,m/p)
然后在计算的时候,只要递归地去计算右半部分就可以了,左半部分可以预处理出阶乘直接算,记得边算边取模就好。

//这是洛谷的模板题
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
ll ksm(ll a,ll b,ll p){a%=p;ll ans=1;while(b){if(b&1){ans=(ans*a)%p;}a=a*a%p;b>>=1;}return ans;
}
ll a[100001];
ll cm(ll n,ll m,ll p){if(m>n)return 0;return (a[n]*(ksm(a[m],p-2,p))%p*(ksm(a[n-m],p-2,p))%p);
}
ll lucas(ll n,ll m,ll p){if(m==0)return 1;return (cm(n%p,m%p,p)%p*lucas(n/p,m/p,p)%p);
}
int main(){int T;scanf("%d",&T);for(int o=1;o<=T;o++){ll n,m,p;scanf("%lld%lld%lld",&n,&m,&p);memset(a,0,sizeof(a));a[0]=1;for(int i=1;i<=100000;i++){a[i]=(a[i-1]*i)%p;}printf("%lld\n",lucas(n+m,n,p));}return 0;
}

4.中国剩余定理(CRT):
用来求线性同余方程组,常用作合并答案
具体自己百度,我也没很弄懂,只是背了公式。

//代码未经测试,极有可能出错,仅供参考
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll q=exgcd(b,a%b,y,x);y-=a/b*x;return q;
}
ll inv(ll a,ll p){ll x,y;exgcd(a,p,x,y);return (x+p)%p;
} 
ll CRT(int n,ll *a,ll *m){ll M=1;for(int i=1;i<=n;i++){M*=m[i];}ll ans=0;for(int i=1;i<=n;i++){ll t=M/m[i];ll x=inv(t,m[i]);ans=(ans+a[i]*t*x)%M;}return (ans+M)%M;
}
int n;
ll a[100001];
ll m[100001];
int main(){return 0;
}

好多算法我还在看还没搞懂,之后发吧,比如什么扩展lucas

这篇关于一名提高选手的数论之路(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

借助AI快速提高英语听力:如何获得适合自己的听力材料?

英语听力是英语学习中的一个重要组成部分,它对于提高语言理解和交流能力至关重要。可理解性学习(comprehensible input)是语言习得理论中的一个概念,由语言学家Stephen Krashen提出,指的是学习者在理解语言输入的同时,自然而然地习得语言。 Krashen认为,当学习者接触到稍微超出他们当前语言水平的输入时,他们会自然地习得语言。这个稍微超出的部分被称为“i+1”,其中“i

三、MyBatis实践:提高持久层数据处理效率

三、MyBatis实践:提高持久层数据处理效率 目录 一、Mybatis简介 1.1 简介1.2 持久层框架对比1.3 快速入门(基于Mybatis3方式) 二、MyBatis基本使用 2.1 向SQL语句传参 2.1.1 mybatis日志输出配置2.1.2 #{}形式2.1.3 ${}形式 2.2 数据输入 2.2.1 Mybatis总体机制概括2.2.2 概念说明2.2.3 单个简单类型

使用Rcpp提高性能之入门篇

C++能解决的瓶颈问题有: 由于迭代依赖于之前结果,循环难以简便的向量化运算递归函数,或者是需要对同一个函数运算成千上万次R语言缺少一些高级数据结构和算法 我们只需要在代码中写一部分C++代码来就可以处理上面这些问题。后续操作在Windows下进行,你需要安装Rtools,用install.packages("Rcpp")安装新版的Rcpp,最重要一点,你需要保证你R语言时不能是C:/Progr

如何提高Github的访问速度

最近总觉得Github的访问速度变慢了,导致我的工作效率也肉眼可见的降低了,主要体现在代码数量和质量的双重降低。 为了解决这一问题,我通过网络检索找到了一个非常好的工具,叫做dev-sidecar (https://github.com/docmirror/dev-sidecar), 这个工具的好处在于,图形化界面,完美解决了windows和MacOS上的问题,但是问题也出在图形化界面上,这意味

C语言编程:青年歌手参加歌曲大奖赛,有10个评委打分(满分10分),去掉最高最低分后,试编程求选手的平均得分

C语言编程:青年歌手参加歌曲大奖赛,有10个评委打分(满分10分),去掉最高最低分后,试编程求选手的平均得分: 代码如下: #include<stdio.h>void main(){int sum = 0,i;double avg,b;int a[10];int max,min;for(i=0;i<10;i++){scanf("%d",&a[i]);if(i==0)//只有第一次赋值m

python | rapidjson,一个实用的 提高JSON处理效率 Python 库!

本文来源公众号“python”,仅用于学术分享,侵权删,干货满满。 原文链接:rapidjson,一个实用的 Python 库! 大家好,今天为大家分享一个实用的 Python 库 - rapidjson。 Github地址:https://github.com/python-rapidjson/python-rapidjson 在现代应用程序开发中,JSON(JavaScript Obj

计算质数通过分区(Partition)提高Spark的运行性能

在Sortable公司,很多数据处理的工作都是使用Spark完成的。在使用Spark的过程中他们发现了一个能够提高Spark job性能的一个技巧,也就是修改数据的分区数,本文将举个例子并详细地介绍如何做到的。 查找质数   比如我们需要从2到2000000之间寻找所有的质数。我们很自然地会想到先找到所有的非质数,剩下的所有数字就是我们要找的质数。   我们首先遍历2到2000000之间的每个数

Android开发实用必备的几款插件,提高你的开发速度

1.GsonFormat 使用方法:快捷键Alt+S也可以使用Alt+Insert选择GsonFormat,作用:速将json字符串转换成一个Java Bean,免去我们根据json字符串手写对应Java Bean的过程。 2.ButterKnife Zelezny 又叫黄油刀 使用方法:Ctrl+Shift+B 作用:快速的绑定资源的id。和findViewbuId说再见。 3.Parcel

如何利用数据仓库进行业务分析:一名大数据工程师的视角

在大数据时代,数据的有效利用对企业的成功至关重要。 本文将基于上面的流程图,详细介绍如何利用数据仓库进行业务分析,并提供实际的例子和代码演示,以帮助读者更好地理解和应用相关技术。 数据仓库的基本流程 上图展示了一个典型的数据仓库流程,包括以下几个主要环节: 业务系统数据接入:业务系统等数据源将数据导入数据仓库。数据仓库建设:规划、建设数据仓库,包括数据模型设计和数据集成。数据分析需求获

【Rust日报】2021-05-13 -- Tracing Prism - 提高日志文件可读性的 Web 程序

Szyszka - 简单好用的批量文件重命名工具 Szyszka 使用 Rust 和 GTK3 创建,具有简单明了的 GUI ,适用于 Linux,Max,Windows。支持多种重命名规则:替换、清除、修改、自定义等。 Github: https://github.com/qarmin/szyszka Snap: https://snapcraft.io/szyszka Tracing Pr