数论模板,待更新。。。
2016-05-12 17:38
337 查看
整数快速幂
LL My_Pow(LL x,LL n){//返回x^n
LL ret=1;
while(n>0){
if(n&1){
ret*=x;
}
x*=x;
n>>=1;
}
return ret;
}
a*b%c
LL Mult_Mod(LL a,LL b,LL c){//返回a*b%c
a%=c;
b%=c;
LL ret=0;
LL tmp=a;
while(b){
if(b&1){
ret+=tmp;
if(ret>c)ret-=c;//%c
}
tmp<<=1;
if(tmp>c)tmp-=c;
b>>=1;
}
return ret;
}
a^b%c
LL Pow_Mod(LL a,LL b,LL c){//返回a^b%c
LL ret=1;
LL temp=a%c;
while(b){
if(b&1)ret=Mult_Mod(ret,temp,c);
temp=Mult_Mod(temp,temp,c);
b>>=1;
}
return ret;
}
一元线性同余方程;
ax+ny=b;
令d=gcd(a,n);
当d|b时,方程有d个解(有d个不同的x),否则无解;ax0+ny0=d;
可得ax+by=c的一个解x=x0*c/d;
那么通解xi=x0+i(n/d);0<=i<=d-1
最小正解x=(x0%(n/d)+n/d)%(n/d);
x0%(n/d) 把x0调到了(-(n/d-1),n/d-1)的位置
+n/d把它变成正数,取模变成最小的正解
每一步计算得到的ans都是通解的一部分;
素数打表:线性筛
void getprim(){
memset(prim,0,sizeof(prim));
for(int i=2;i<=SIZE;i++){
if(!prim[i])prim[++prim[0]]=i;
for(int j=1;j<=prim[0]&&prim[j]<=SIZE/i;j++){
prim[prim[j]*i]=1;
if(i%prim[j]==0)break;
}
}
printf("%d\n",prim[0]);//prim[0]表示2-size内的素数的个数
}
普通筛
int prim[SIZE];
void get_prim(){
memset(prim,0,sizeof(prim));
for(LL i=2;i<SIZE;i++){
if(!prim[i]){
prim[++prim[0]]=i;
for(LL j=i*i;j<SIZE;j+=i)
prim[j]=1;
}
}
}
判断一个数是否是素数,prim为sqrt(n)内的素数
bool is_prim(int n){
if(n==1)return false;
for(int i=1,k=(int)sqrt((double)n);prim[i]<=k;i++)
if(n%prim[i]==0)return false;
return true;
}
ex_gcd
long long extend_gcd(long long a,long long b,long long &x,long long &y){
if(a==0&&b==0)return -1;//无gcd
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
long long gcd(long long a,long long b){
if(b==0)return a;
return gcd(b,a%b);
}
LL My_Pow(LL x,LL n){//返回x^n
LL ret=1;
while(n>0){
if(n&1){
ret*=x;
}
x*=x;
n>>=1;
}
return ret;
}
a*b%c
LL Mult_Mod(LL a,LL b,LL c){//返回a*b%c
a%=c;
b%=c;
LL ret=0;
LL tmp=a;
while(b){
if(b&1){
ret+=tmp;
if(ret>c)ret-=c;//%c
}
tmp<<=1;
if(tmp>c)tmp-=c;
b>>=1;
}
return ret;
}
a^b%c
LL Pow_Mod(LL a,LL b,LL c){//返回a^b%c
LL ret=1;
LL temp=a%c;
while(b){
if(b&1)ret=Mult_Mod(ret,temp,c);
temp=Mult_Mod(temp,temp,c);
b>>=1;
}
return ret;
}
一元线性同余方程;
ax+ny=b;
令d=gcd(a,n);
当d|b时,方程有d个解(有d个不同的x),否则无解;ax0+ny0=d;
可得ax+by=c的一个解x=x0*c/d;
那么通解xi=x0+i(n/d);0<=i<=d-1
最小正解x=(x0%(n/d)+n/d)%(n/d);
x0%(n/d) 把x0调到了(-(n/d-1),n/d-1)的位置
+n/d把它变成正数,取模变成最小的正解
每一步计算得到的ans都是通解的一部分;
素数打表:线性筛
void getprim(){
memset(prim,0,sizeof(prim));
for(int i=2;i<=SIZE;i++){
if(!prim[i])prim[++prim[0]]=i;
for(int j=1;j<=prim[0]&&prim[j]<=SIZE/i;j++){
prim[prim[j]*i]=1;
if(i%prim[j]==0)break;
}
}
printf("%d\n",prim[0]);//prim[0]表示2-size内的素数的个数
}
普通筛
int prim[SIZE];
void get_prim(){
memset(prim,0,sizeof(prim));
for(LL i=2;i<SIZE;i++){
if(!prim[i]){
prim[++prim[0]]=i;
for(LL j=i*i;j<SIZE;j+=i)
prim[j]=1;
}
}
}
判断一个数是否是素数,prim为sqrt(n)内的素数
bool is_prim(int n){
if(n==1)return false;
for(int i=1,k=(int)sqrt((double)n);prim[i]<=k;i++)
if(n%prim[i]==0)return false;
return true;
}
ex_gcd
long long extend_gcd(long long a,long long b,long long &x,long long &y){
if(a==0&&b==0)return -1;//无gcd
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
long long gcd(long long a,long long b){
if(b==0)return a;
return gcd(b,a%b);
}
相关文章推荐
- startActivity报错
- 精通UIPasteboard粘贴板
- VirtualBox,vagrant,ubuntu,nodejs环境搭建
- Java 更新jdk过程总结 (全)
- 从Handler+Message+Looper源码带你分析Android系统的消息处理机制
- 粗颗粒度权限控制
- Linux客户端远程访问windows服务器
- 《程序员面试宝典读书笔》读书笔记7
- proxy 出现乱码问题解决 lua
- Google Map 学习过程中的代码
- iOS一些常用的判断条件
- 仿QQ侧滑,如何一个关闭一个开启
- 选择排序法——1到10000
- 超级简单的全选
- Ubuntu系统如何修改主机名
- web前端性能优化
- shopncv4 短信接口 提供商 中国短信网
- [自动化平台系列] - 初次使用 Macaca-前端自动化测试(3)
- .net RAW(16)与GUID互相转换
- cookie实现自动登陆原理