扩展欧几里得是用于求解不定方程、线性同余方程和乘法逆元的常用算法。

下面是代码:

 function Euclid(a,b:int64;var x,y:int64):int64;
var t:int64;
begin
if b= then
begin
x:=;y:=;exit(a);
end else
begin
Euclid:=Euclid(b,a mod b,x,y);
t:=x;x:=y;y:=t-(a div b)*y;
end;
end;

下面出现了其中后两个应用。(虽然个人认为不定方程和同余方程可以互相转换)


POJ1061 

  线性同余简单应用。

 program poj1061;
var x0,y0,m,n,L,a,b,d,x,y,tem,c:int64; function f(a:int64):int64;
begin
if a< then a:=a+(-a) div L*L;
while a<= do a:=a+L;
exit(a);
end; function Euclid(a,b:int64;var x,y:int64):int64;
var t:int64;
begin
if b= then
begin
x:=;y:=;exit(a);
end else
begin
Euclid:=Euclid(b,a mod b,x,y);
t:=x;x:=y;y:=t-(a div b)*y;
end;
end; begin
readln(x0,y0,m,n,L);
a:=f(m-n);b:=L;
d:=Euclid(a,b,x,y);
c:=f(y0-x0);
// 由于扩展欧几里得算法里要求最大公约数,所以要处理成正数
// 根据同余方程的性质,a,b,c加上L对答案不会有影响。
if c mod d<> then
begin
writeln('Impossible');
// 同余方程有整数解的条件。
halt;
end;
x:=x*c div d;
if x< then x:=x+(-x) div (b div d)*(b div d);
while x< do x:=x+(b div d);
//这里是保证跳的步数为自然数
if x-(b div d)>= then x:=x-x div (b div d)*(b div d);
while x-(b div d)>= do x:=x-(b div d);
//这里是保证跳的步数是最小步数
writeln(x);
end.

POJ1845

  由于姿势不大对...交了很多遍处理了很多细节才过。

  因此觉得这道题挺好的...因为本来觉得只是一道求逆元的模板题,但实际上想要A掉它并不容易。

  首先先讲一下算法部分。

  求a^b的约数和。

  = (p1^0+p1^1+...p1^k1)*(p2^0+p2^1...+p2^k2)...*(pn^0+pn^1+...pn*kn) (p为a的质因子,ki为第i个质因子的个数)

  我们可以用素数拆分,然后对于每一部分,用等比数列求和公式。

  分子部分可以用取模的快速幂解决。

  分母部分乘上其逆元。

  大体的思路已经构建好了。

  但是细节超级超级多.....>_< 已经被搞疯啦...直接在代码里贴出来好了。


 program poj1845;
const tt=;
var a,b,ans,k:int64;
i:longint; function Euclid(a,b:int64;var x,y:int64):int64;
var t:int64;
begin
if b= then
begin
x:=;y:=;exit(a);
end else
begin
Euclid:=Euclid(b,a mod b,x,y);
t:=x;x:=y;y:=t-(a div b)*y;
end;
end; function mul(a,b:int64):int64;
var ans,w:int64;
begin
ans:=;w:=a mod tt;
while b> do
begin
if b and = then ans:=(ans*w)mod tt;
w:=(w*w) mod tt;
b:=b >> ;
end;
exit(ans);
end; function inverse(p:int64):int64;
var x,y:int64;
begin
if Euclid(p,tt,x,y)<> then exit(-) else
begin
while x<tt do inc(x,tt);
x:=x mod tt;
// 我们需要找到一个正的逆元,根据x= x0+b/d*t可以得到,d=,b=tt。所以只要不停加上tt即可。
// 虽然刚开始的直觉就是不停加上tt直到找到一个正的为止...但是实际上是有理论依据的。
exit(x);
end;
end; begin
while not eof do
// 由于被多组数据坑过...所以不管怎样还是加上为好
begin
readln(a,b);
if a= then
begin
writeln();
// 这是一个细节需要特判
continue;
end;
ans:=;
for i:= to trunc(sqrt(a)) do if a mod i= then
begin
k:=;
while a mod i= do
begin
inc(k);a:=a div i;
end;
k:=k*b;
ans:=((ans*((mul(i,k+)+tt-) mod tt)) mod tt*inverse(i-))mod tt;
// 本来这里的inverse(i-)也需要处理i mod tt=的情况,但是由于数据范围i的上限正好是7000多不用考虑。
end;
// 刚开始下面的一块都忘了QAQ
if a<> then
begin
if a mod tt= then
begin
ans:=ans*(b+) mod tt;
// 这是最容易忽略的一个细节。当a mod tt=的时候,inverse(i)是算不出来的,这个时候思考一下便发现,a mod tt=
// a^k mod tt=,所以最后mod tt余数就是b+.
// 刚开始由于直接输出了(b+) WA了一次...后来发现剩下的a不一定是a本身。
end else
begin
i:=a;k:=b;
ans:=((ans*((mul(i,k+)+tt-) mod tt)) mod tt*inverse(i-)) mod tt;
end;
end;
writeln(ans);
end;
end.

[POJ1845&POJ1061]扩展欧几里得应用两例的更多相关文章

  1. CSU 1446 Modified LCS 扩展欧几里得

    要死了,这个题竟然做了两天……各种奇葩的错误…… HNU的12831也是这个题. 题意: 给你两个等差数列,求这两个数列的公共元素的数量. 每个数列按照以下格式给出: N F D(分别表示每个数列的长 ...

  2. POJ1061 青蛙的约会(扩展欧几里得)

    题目链接:http://poj.org/problem?id=1061 青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

  3. POJ1061:青蛙的约会+POJ2115C Looooops+UVA10673Play with Floor and Ceil(扩展欧几里得)

    http://poj.org/problem?id=1061 第一遍的写法: #include <iostream> #include <stdio.h> #include & ...

  4. [poj1061]青蛙的约会<扩展欧几里得>

    题目链接:http://poj.org/problem?id=1061 其实欧几里得我一直都知道,只是扩展欧几里得有点蒙,所以写了一道扩展欧几里得裸题. 欧几里得算法就是辗转相除法,求两个数的最大公约 ...

  5. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C.Ray Tracing (模拟或扩展欧几里得)

    http://codeforces.com/contest/724/problem/C 题目大意: 在一个n*m的盒子里,从(0,0)射出一条每秒位移为(1,1)的射线,遵从反射定律,给出k个点,求射 ...

  6. UVA 12169 Disgruntled Judge 枚举+扩展欧几里得

    题目大意:有3个整数 x[1], a, b 满足递推式x[i]=(a*x[i-1]+b)mod 10001.由这个递推式计算出了长度为2T的数列,现在要求输入x[1],x[3],......x[2T- ...

  7. UVA 10090 Marbles 扩展欧几里得

    来源:http://www.cnblogs.com/zxhl/p/5106678.html 大致题意:给你n个球,给你两种盒子.第一种盒子每个盒子c1美元,可以恰好装n1个球:第二种盒子每个盒子c2元 ...

  8. POJ 1061 青蛙的约会 扩展欧几里得

    扩展欧几里得模板套一下就A了,不过要注意刚好整除的时候,代码中有注释 #include <iostream> #include <cstdio> #include <cs ...

  9. 【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

    Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到C ...

随机推荐

  1. beego orm

    http://beego.me/docs/mvc/model/overview.md go get github.com/astaxie/beego/orm Simple Usage package ...

  2. 位运算 & 网络序字节序

    一.初识位运算 位运算,见词明意,二进制运算,通常需要将运算数转换为二进制再进行处理,如果是在程序语言中则无需自己进行进制转换,基本的位操作符有如下几种:与(&).或(|).异或(^).取反( ...

  3. ACE_Select_Reactor_T 介绍 (2)

    本章目录 ACE_Select_Reactor_T 介绍 类继承图 类协作图 类主要成员变量 事件处理函数调用图 事件处理主流程 handle_events 函数流程 handle_events_i ...

  4. Java并发基础--线程安全

    一.线程安全 1.线程安全的概念 线程安全:某个类被单个线程,或者多个线程同时访问,所表现出来的行为是一致,则可以说这个类是线程安全的. 2.什么情况下会出现线程安全问题 在单线程中不会出现线程安全问 ...

  5. python基础训练营04-函数

    任务四  函数的关键字 函数的定义 函数参数与作用域 函数返回值 一.函数的关键字: def 二.函数的定义: 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号 ...

  6. direct.h头文件(对目录操作)

    chdir()改变当前目录的函数原形:int chdir(const char *path)功能:把由path指定的目录改为当前目录.path参数中可以指定驱动器号,如“a:\\ddd”, 但只是改变 ...

  7. sql声明变量存储查询结果

    with t as 查到条件数据,然后在下面使用到t,用exists做判断会非常慢,改成left join会快很多. 我使用的数据库时2008Sql r2. 文章:SQL数据库中临时表.临时变量和WI ...

  8. Java作业09-异常

    6. 为如下代码加上异常处理 byte[] content = null; FileInputStream fis = new FileInputStream("testfis.txt&qu ...

  9. C++ Profiler工具之初体验

    http://www.cnblogs.com/likwo/archive/2012/12/20/2826988.html 转 http://www.cnblogs.com/lenolix/archiv ...

  10. B - 整数区间

    B - 整数区间 Time Limit: 1000/1000MS (C++/Others) Memory Limit: 65536/65536KB (C++/Others) Problem Descr ...