博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HDU](1576) A/B ----扩展欧几里德(数论)
阅读量:4315 次
发布时间:2019-06-06

本文共 2255 字,大约阅读时间需要 7 分钟。

A/B

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5717    Accepted Submission(s): 4481


Problem Description
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
 

Input
数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
 

Output
对应每组数据输出(A/B)%9973。
 

Sample Input
 
2 1000 53 87 123456789
 

Sample Output
 
7922 6060

一、欧几里德算法就是我们熟悉的辗转相除法用来求两个数的最大公约数。即:gcd(a,b)=gcd(b,a%b).

二、那么什么是扩展欧几里德算法?扩展欧几里德算法是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。

解题思路:

1)  n=a%9973, 那么n=a-(a/9973)*9973(关于这个式子的解释:如:7%3=2...1 这是我们在日常数学中的写法,那么我们可以把这个式子转换一下,2=7/3,1=7-2*3,1=7-(7/3)*3),注意:a/b所得是整数。

2)    然后我们要把现在有的条件转换成扩展欧几里德,已知n,b,gcd(b,9973) (利用扩展欧几里德,我们可以知道gcd(b,9973)=1=bx+9973y)。题目让我们去求(a/b)%9973,我们如果把a/b求出来那么答案也就知道了。不妨设 a/b=x1,那么a=b*x1,那么1中的式子通过替换得到:n=bx1-(bx1/9973)*9973 ,咦~有没有发现,如果设y1=-(bx1/9973).那么我们的式子最终变成了n=bx1+9973y1  是不是快和已知的那个gcd(b,9973)联系起来了。

3)  通过继续了解扩展欧几里德算,我们了解到欧几里德算法的终止条件为:已经ax+by = gcd(a, b) ,   当a=gcd,b=0的时候终止。那么,这是否给我们求解x,y提供一种思路呢?看,这时候,只要a的系数为1,即x=1.   b的系数为0,即y=0. 这时候我们就有 a *1 + b*0 =gcd 这就是我们算法终止时候的状态,那么我们如何通过最终状态进行反推,求得最初状态的x和y呢?

4)  我们知道ax+by = gcd(a, b) ,那么它的下个状态为b*x1+(a%b)*y1=gcd(b,a%b) 我们知道a%b=a-(a/b)*b,代入式子即    a*y1+b(x1-(a/b)*y1)=gcd(b,a%b) 和原来的式子相比我们发现x=y1,y=x-(a/b)*y1,这样我们就把欧几里德的全过程表示出来了,我们就可以通过递归实现这个算法了。

5)  了解到欧几里德的全过程,我们了也就可以联系我们一开始的两个式子:gcd(b,9973)=1=bx+9973y和n=b*x1+9973*y1,即gcd(b,9973)=1=bx+9973 是我们的最终状态,我们通过递归调用,将x=y1,y=x-(a/b)*y1写在递归调用后面,最后一定能求出 x,如果把最终状态两边同时乘以n 变成n=b*x*n+9973*n*y  即x1=x*n,y1=n*y.。x1就是我们一开始想求得那个a/b !

欧几里德算法是自己的数论入门,也是看了两天,算是理解,如果不明白请戳(这些讲的都比我详细,我也是刚理解):

:http://blog.csdn.net/zhjchengfeng5/article/details/7786595

:http://blog.csdn.net/liuchang54/article/details/44065651

扩展欧几里得算法:http://www.acmerblog.com/extend-gcd-5610.html

#include
#define mod 9973using namespace std;int x;int y;void gcd(int a,int b){ int temp; if(b==0) { x=1; y=0; return; } else { gcd(b,a%b); temp=x; x=y; y=temp-(a/b)*y; }}int main(){ int n; int b; int t; cin>>t; while(t--) { cin>>n>>b; gcd(b,mod); x=(x%mod+mod); x*=n; cout<
<

转载于:https://www.cnblogs.com/WangMeow/p/7536004.html

你可能感兴趣的文章
Xpath提取一个标签里的所有文本
查看>>
11 吐司 Toast 代码案例
查看>>
CKplayer:视频推荐和分享插件设置
查看>>
通过服务修改widgetUI
查看>>
win10连接无线网,开启移动热点,手机连接它手机一直显示获取ip地址中。
查看>>
MapReduce的倒排索引
查看>>
Heterogeneity Activity Recognition Data Set类别
查看>>
服务中的 API 网关(API Gateway)
查看>>
Android--TextView第一个单词大写
查看>>
网友给的链接
查看>>
《2017011.17-构建之法:现代软件工程-阅读笔记3》
查看>>
sourceinsight4
查看>>
C#实现四部电梯的调度
查看>>
Android SDK版本和ADT版本
查看>>
TCL的艰难生存之路
查看>>
Flask最强攻略 - 跟DragonFire学Flask - 第五篇 做一个用户登录之后查看学员信息的小例子...
查看>>
Android笔记(四十) Android中的数据存储——SQLite(二) insert
查看>>
newcoder【NOIP2018普及组模拟赛第一次】C题
查看>>
关于PC端页面适应不了手机端的问题 解决方案
查看>>
多线程 基本概念
查看>>