数论(欧几里得,扩展欧几里得,欧拉)

  今天考试了,三道题分别是求欧拉,逆欧拉,欧拉求和

  对于我这样的蒟蒻来说,我选择狗带。

  爆零稳稳的。

  现在整理一下;

  φ(n)(欧拉函数值)为不大于n的正整数中与n互质的数的个数;

  有几条这样的性质:

    1.欧拉函数是积性函数,但不是完全积性函数,即φ(mn)=φ(n)*φ(m)只在(n,m)=1时成立.

    2.对于一个正整数N的素数幂分解N=P1^q1*P2^q2*...*Pn^qn.

    φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn).

    3.除了N=2,φ(N)都是偶数.

    4.设N为正整数,∑φ(d)=N (d|N).

  根据其中第2条性质,我们可以想出求φ(n)的代码

  思路:

    n分解质因数

    代码:

    

#include<cstdio>
#include<iostream>

using namespace std;

long long int n,head=2,ans=1,ans2=1;
bool yinshu[500001000];

int main()
{
    cin>>n;
    long long int cur=n;
    while(head<=n)
    {
        if(cur==1) break;
        if(cur%head==0)
        {
            cur/=head;
            yinshu[head]=true;
        }
        else head++;
    }
    for(int i=2;i<=head;i++)
    {
        if(yinshu[i]==true)
        {
            ans*=i-1;
            ans2*=i;
        }
    }
    ans*=n/ans2;
    cout<<ans<<endl;
    return 0;
}

  当然,其中分解质因数的时候,还可以打一张素数表,但是如果你给的数是大于10^18次方的质数,这个代码无能为力;

  有个算法叫做Miller_Rabin算法,可以很快的判断一个数是不是素数;

  欧几里得算法:

  1.gcd(欧几里得):

  gcd可以用来求最大公约数,直接上代码:

int gcd(int m,int n)
{
    if(n==0) return m;
    else return gcd(n,m%n);
}

  2.扩展欧几里得:

  对于不完全为0的整数a,b存在ax+by==gcd(a,b);

  扩展欧几里得可用于求出x,y;

  根据gcd(欧几里得)可以得出gcd(a,b)==gcd(b,a%b);

  所以

  当b==0时,存在ax+0*y==gcd(a,b)==gcd(a,0)==a;

  所以当b==0时,x==1,y==0;

  同时ax+by==gcd(a,b),bx1+a%by1==gcd(b,a%b);

  所以ax+by==bx1+(a-a/b*b)*y1;

        ax+by==bx1+ay1-a/b*b*y1;

    ax+by==ay1+b(x1-a/b*y1);

    即:

    x==y1,y==x1-a/b*y1;

    由此可得出扩展欧几里得求x,y的递归式,上代码:

int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x==1,y==0;
        return a;
    }
    int r=exgcd(b,a%b,x,y),tmp;
    tmp=x,x=y,y=tmp-a/b*y;
    return r;
}

  接下来是关于扩展欧几里得的一道信息题:

  题目 codevs 1200 同余方程

1200 同余方程

2012年NOIP全国联赛提高组

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题解

题目描述 Description

求关于 x 同余方程 ax ≡ 1 (mod b)的最小正整数解。

输入描述 Input Description

输入只有一行,包含两个正整数 a, b,用 一个 空格隔开。

输出描述 Output Description

输出只有一行包含一个正整数x0,即最小正整数解,输入数据保证一定有解。

样例输入 Sample Input

3 10

样例输出 Sample Output

7

数据范围及提示 Data Size & Hint

【数据范围】
对于 40%  的数据, 2 ≤b≤ 1,000 ;
对于 60% 的数据, 2 ≤b≤ 50,000,000 
对于 100%  的数据, 2 ≤a, b≤ 2,000,000,000

  思路:

    题目是求关于x的同余方程ax ≡ 1 (mod b)的最小解

    ax ≡ 1 (mod b),即a*x%b==1;

    原式可简化成ax-ax/b*b==1;

    设-ax/b为y

    则原式成为ax+bx==1 变为可用扩展欧几里得求的数;

    但是求出的x不一定大于等于0

    所以还要有一个小小的转换

    即

int cnm=gcd(a,b);
while(x<0) x+=(b/cnm),y-=(a/cnm);

    然后输出x即可ac;

    上代码:

#include<cstdio>

#define ll long long

using namespace std;

ll int a1,b1,x1,y1;

ll int exgcd(ll int a,ll int b,ll int &x,ll int &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    ll int r=exgcd(b,a%b,x,y),tmp;
    tmp=x,x=y,y=tmp-a/b*y;
    return r;
}

int main()
{
    scanf("%lld%lld",&a1,&b1);
    ll int cnm=exgcd(a1,b1,x1,y1);
    while(x1<0) x1+=(b1/cnm),y1-=(a1/cnm);
    printf("%lld\n",x1);
    return 0;
}
时间: 2024-11-04 19:33:15

数论(欧几里得,扩展欧几里得,欧拉)的相关文章

POJ 1061 青蛙的约会(欧几里得扩展)

题意:已知青蛙1位置x,速度m,青蛙2位置y,速度n,纬线长度为l,求他们相遇时最少跳跃次数. 思路:设最小跳跃次数为k,则(x + k*m) - (y + k*n) = q*l:经过整理得到k*(n-m) + q*l = y - x:此时k和l为变量.欧几里得扩展中有线性方程a*x+b*y = c,当且仅当c是gdc(a,b)的整数倍的时候,所以这个题我们可以使用这个算法求得一个x0(x0已经被乘以了倍数),故x0为满足题意的一个解,X的解系为x0 + k[b/gcd(a,b)](具体证明不在

欧几里得扩展定理

//poj   1061 思路:两只青蛙跳一次所花费的时间相同,我们设其为t,则x+mt是青蛙A从坐标原点到终点所走的距离,y+nt是B走的距离,要想碰面,则他们相减一定是地面周长的整数倍,设为k*L:则:(x+mt)-(y+nt)=kl;变形得:(m-n)t-(y-x)=kL;即有(m-n)t mod L=y-x;为线性同余方程.此方程有解当且仅当y-x能被m-n和L的最大公约数(记为gcd(m-n,L)),即gcd(m-n,L)|y-x.这时,如果x0是方程的一个解,即当t=x0时,(m-n

hive里的扩展接口

hive里的扩展接口,主要包括CLI(控制命令行接口).Beeline和JDBC等方式访问Hive. CLI和Beeline都是交互式用户接口,并且功能相似,但是语法和实现不同. JDBC是一种类似于编程访问关系型数据库的编程接口. 1.CLI 在UNIX shell环境下输入hive命令可以启用Hive CLI.在CLI下,所有的Hive语句都以分号结束. 在CLI下可以对一些属性做出设置,像是设置底层MapReduce任务中Reducer的实例数.这些信息都详细地记录在在线Hive语言手册中

柯里化与反柯里化

柯里化 什么是柯里化 柯里化(英语:Currying),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术. 柯里化的基础 上面的代码其实是一个高阶函数(high-order function), 高阶函数是指操作函数的函数,它接收一个或者多个函数作为参数,并返回一个新函数.此外,还依赖与闭包的特性,来保存中间过程中输入的参数.即: 函数可以作为参数传递 函数能够作为函数的返回值 闭包 通用实现 var currying

高级语言里的函数在汇编里的实现方式

一. 学习过程 在高级语言中我们为什么要用变量呢?因为我们要存储数据,而且因为要使用循环等语法结构,存储的数据需要不断地变化,变量的特性可以很好地解决这个问题.在前面我已经讨论过了,变量的声明实际上就是在内存中开辟一个内存空间,我们在汇编语言里使用循环,主要是把数据存在si.di等寄存器中来进行操作,存储数据是把数据放在寄存器.内存空间(普通的和栈)里面.编写程序ur1.c,并编译连接: 用debug加载ur1.exe,用u命令查看编译后的机器码和汇编代码: 发现main函数中的代码没有出现,用

js之柯里化与反柯里化

先给大家介绍什么是柯里化与反柯里化 百度翻译: 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的. 柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具

JS的防抖,节流,柯里化和反柯里化

今天我们来搞一搞节流,防抖,柯里化和反柯里化吧,是不是一看这词就觉得哎哟wc,有点高大上啊.事实上,我们可以在不经意间用过他们但是你却不知道他们叫什么,没关系,相信看了今天的文章你会有一些收获的 节流 首先我们来搞一下节流,啥叫节流,就是将高频率触发事件变成低频率触发事件,举个简单的例子,但我们用window.onscroll滚动事件的时候你会发现滚轮滑动一次可能会触发好多次事件, 代码: window.onscroll = function(){ console.log("触发")

数论杂谈——欧几里得算法及扩展欧几里得

数学是oi的重要基础,所以说数论在oi中占据了非常重要的地位,因此,学好数学,对于一个oier来说也是非常重要的. oi中的数学,其实也就和数竞并没有什么区别. 欧几里得法辗转相除法求最大公约数 我们可以证明gcd(a,b)=gcd(b,a%b),也就是我国古代数学智慧的结晶,更相损减术.并且一直递归下去,直到b的值为零,最大公约数值即为a.在这里就不给出详细证明了,大家可以代几个数据去验证它一下.谁叫我数学太菜. 代码如下 int GCD(int a,int b) { if(!b) { ret

欧几里得&amp;扩展欧几里得算法

朴素的欧几里得算法大家应该知道 \(gcd(a,b)\)表示a,b的最大公约数 朴素的欧几里得算法其实就是所谓的辗转相除法 辗转相除法 \(gcd(a,b)=gcd(b,a\) \(mod\) \(b)\) 证明如下: \(设r=a\) \(mod\) \(b\) \(=a-\lfloor\frac{a}{b}\rfloor*b\),\(p=gcd(a,b)\); 则\[a=xp,b=yp\] 代入可得\[r=xp-\lfloor\frac{xp}{yp}\rfloor*yp\] 提公因式得\[

简单数论总结2——同余方程与扩展欧几里得算法

在上一次总结过后鸽了没多久其实是快要开学赶紧来肝上两篇 今日内容--同余方程和扩展欧几里得算法 同余 同余的定义:若存在两个整数a,b,使得(a - b) MOD P为0,则称作a与b在MOD P的情况下同余 换种通俗的说法,就是,a MOD P与b MOD P相等 记作  \( a\equiv b (mod P) \) 对于整数a,b,c和自然数m,n 同余具有以下性质: 自反性:\( a\equiv a (mod P) \) 对称性:若存在\( a\equiv b (mod P) \) ,则