码迷,mamicode.com
首页 > 其他好文 > 详细

快速幂以及相关内容

时间:2017-10-20 14:37:42      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:oid   ati   存在   ace   bmp   st3   operator   因子   方便   

数论

标签(空格分隔): 数论 @zhshh 听课笔记

2017-10-17


 

欧拉函数

1.求phi
8407 12844

 

int phi(int n){
	int ans=n;
//	int num=n;//num用来标记flag的总数【详见下面POJ2773】
	for(int i=2;i*i<=n;i++){
		if(n%i==0){
			ans-=ans/i;
			while(n%i==0){
				n/=i;
			}
			/*    int m=1;
                while(m*j<=n){
                    flag[m*j]=true;
                }
            */
		}
	}
	if(n!=1)ans-=ans/n;
	return ans;
}

POJ2773

输入n,k求与n不互质的第k大整数

设数a,n若a,n不互质,即存在m是a,n因子,则m是a,n,n+a因子
同理若互质,n=k1m,a=k2m+b,则n+a=(k1+k2)*m+b;
因此1..n n+1..2n ....是否互质是循环的
在1..n内在去求第k % φ(n)个数即可
(用筛的方式(n的质因子)?)
后面两步还可以合并到了前面求phi时添加如下代码

 

int m=1;
while(m*j<=n){
    flag[m*j]=true;
}

POJ3090

Visible Lattice Points
技术分享
输入边长n,输出从(0,0)可以看到的所有点
IN:4 2 4 5 231(空格是换行符)
OUT:1 2 5 13 21 32549

样例:

 

快速幂及其变形

快速幂
快速乘
快速幂/乘取模
矩阵快速幂(矩阵的处理如果定义结构体matrix并且重载了*和*=,代码与快速幂一样)

01矩阵快速幂
这些的思想一样,都是把func(type a,指数 b,int mod)的指数b位运算,达到log的速度,而其中的乘法/加法还是朴素算法。
加速是在幂(快速乘的乘)时进行的

 

快速幂

 

long long poww(int a,int b){
	long long ans=1,base=a;
	if(a==0)return 0;
	while(b){
		if(b&1!=0){
			ans*=base;
		}
		base*=base;
		b>>=1;
	}
	return ans;
}
//这里的乘法是朴素乘法,快速是应用到了b的运算上

 

快速乘

 

long long mul(int a,int b){
	long long ans=0,base=a;//加法ans初始值为0
	if(a==0)return 0;
	while(b){
		if(b&1!=0){
			ans+=base;//这步改成了加法
		}
		base+=base;//同上改成加法
		b>>=1;
	}
	return ans;
}

 

快速幂取模

最保险的方法是取模4次,不过在确定不会溢出的时候可以减少(提高速度)

 

long long poww_mod1(int a,int b,int c){
	long long ans=1,base=a%c;
	if(a==0)return 0;
	while(b){
		if(b&1!=0){
			ans=(ans*base)%c;
		}
		base=(base*base)%c;
		b>>=1;
	}
	return ans%c;
}

只有一个取模的写法,比如洛谷P1226 取余+快速幂 答案会溢出,AC前两个,WA后面4个

 

long long poww_mod2(int a,int b,int c){
	long long ans=1,base=a;
	if(a==0)return 0;
	while(b){
		if(b&1!=0){
			ans=(ans*base)%c;
		}
		base=base*base;
		b>>=1;
	}
	return ans;
}

 

矩阵

定义:

 

#define n 5

struct matrix {
	int x[n+1][n+1];
	matrix() {
		memset(x,0,sizeof(x));
	}
	void fill(int q) {
		int maxx=sizeof(x)/sizeof(int);
		int* p=&x[0][0];
		while(maxx>0) {
			*p=q;
			p++;
			maxx--;
		}
	}
};

写成了struct主要是为了方便重载运算符,以及各种初始化等,但是注意如果直接开很大的数组,会爆栈(例如上例#define n 1005之后运行,程序立马崩溃)
矩阵的处理如果定义结构体matrix并且重载了*和*=,代码与快速幂一样

 

乘法

 

matrix operator *(matrix a,matrix b)
{
	matrix ans;
	ans.fill(0);
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			for(int k=1; k<=n; k++) {
				ans.x[i][j]+=a.x[i][k]*b.x[k][j];
			}
		}
	}
	return ans;
}

 

快速乘

 

同余

因为x=x0*c/gcd ,所以整数解充要条件是c mod gcd==0

gcd (a,b)=gcd(b,a\%b)=gcd(c,0)=c=ax+by;
gcd(a,b)=gcd(b,a\%b)=c
ax+by=bx‘+a\%by‘
ax+by=bx‘+(a-a/b*b)y‘
=ay‘+b(x‘-a/by‘)
x=y‘
y=x‘-a/b*y‘

 

扩展欧几里得

 

#include <iostream>
using namespace std;
int exgcd(int a,int b,int &x,int &y){
	if(b==0){
	x=1;
	y=0;
	return a;}//上面部分与gcd类似,后面根据上面证明可得x,y与x‘,y‘递推公式,不断回溯
	int ret=exgcd(b,a%b,x,y);
	int temp=x;
	x=y;
	y=temp-a/b*y;
	return ret;
}
int main(){
	int x,y;
	int a=15;
	int b=12;
	int gcd=exgcd(a,b,x,y);//gcd为最大公约数
	int c=63;
	cout<<gcd;
	if(c % gcd==0)cout<<endl<<"have int root";//因为方程的求解
	cout<<endl<<x*c/gcd<<endl<<y*c/gcd;
	cout<<endl<<b<<endl<<gcd;
	int t=b/gcd;
	cout<<endl<<x%t;
	cout<<endl<<(x%t+t)%t;
}

 

void exgcd(a,b,&x,&y){
    if( b==0)x=1,y=0;
    else
    ss(b,a%b,y,x),y-=x*(a/b)
}

shuashua树上差分

ZHxxxxxxx

快速幂以及相关内容

标签:oid   ati   存在   ace   bmp   st3   operator   因子   方便   

原文地址:http://www.cnblogs.com/zhshh/p/7699312.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!