【扩展欧几里得】hdu 1576 A/B

本文介绍了一种解决大数除法问题的方法,特别是如何计算(A/B)%9973,其中A非常大,仅给出A%9973的值,并确保A能被B整除且B与9973互质。提供了两种解决方案:逆元解法和扩展欧几里得算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A/B

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


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
 

逆元解法:
#include<stdio.h>
#define MOD 9973
//******************************
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
    if(a==0&&b==0) return -1;//无最大公约数
    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;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
    long long x,y;
    long long d=extend_gcd(a,n,x,y);
    if(d==1) return (x%n+n)%n;
    else return -1;
}

int main()
{
    int T;
    int n,B;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&B);
        int x=mod_reverse(B,MOD);
        printf("%d\n",n*x%MOD);
    }
    return 0;
}

扩展欧几里得求ax+by=c解法:
先设(A/B)%9973 = k
--->> A/B = k + 9973 * x
--->> A = kB + 9973*x*B
--->> kB % 9973 = n
--->> 则kB = n + 9973 * y
--->> 则 kB + 9973 *y = n,y属于整数,可正可负
--->>(k / n) * B + 9973*(y / n) = 1
--->> 又gcd(B,9973)= 1
--->> 所以求出k = x *n %9973
#include <iostream>
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <algorithm>
#include <functional>
#define PI acos(-1)
#define eps 1e-8
#define inf 0x3f3f3f3f
#define debug(x) cout<<"---"<<x<<"---"<<endl
typedef long long ll;
using namespace std;

///求ax+by=gcd(a,b)的特解x0,y0以及gcd(a,b)
long long exgcd(long long a, long long b, long long &x, long long &y)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    long long ans = exgcd(b, a % b, x, y);
    long long temp = x;
    x = y;
    y = temp - (a / b) * y;
    return ans;  ///ans=gcd(a,b);
}
///求ax=c(mod b),即求ax+by=c的最小非负整数解
long long cal(long long a, long long b, long long c)
{
    long long x, y;
    long long gcd = exgcd(a, b, x, y);
    if (c % gcd != 0)
    {
        return -1;
    }
    x = x * (c / gcd);
    int t = b / gcd;
    if (t < 0)
    {
        t = -t;
    }
    long long ans = x % t;
    if (ans <= 0)
    {
        ans += t;
    }
    return ans;
}
int main()
{
    long long t, n, b;
    cin >> t;
    while (t--)
    {
        cin >> n >> b;
        long long ans = cal(b, 9973, 1);
        cout << ans*n % 9973 << endl;
    }
    return 0;
}
///求ax+by=c的特解:
///x0=x0*(c/gcd);
///y0=y0*(c/gcd);

///求通解:
///x=x0+(b/gcd)*k;
///y=y0-(a/gcd)*k;

/************************************************
┆  ┏┓   ┏┓ ┆
┆┏┛┻━━━┛┻┓ ┆
┆┃       ┃ ┆
┆┃   ━   ┃ ┆
┆┃ ┳┛ ┗┳ ┃ ┆
┆┃       ┃ ┆
┆┃   ┻   ┃ ┆
┆┗━┓    ┏━┛ ┆
┆  ┃    ┃  ┆      
┆  ┃    ┗━━━┓ ┆
┆  ┃  AC代马   ┣┓┆
┆  ┃           ┏┛┆
┆  ┗┓┓┏━┳┓┏┛ ┆
┆   ┃┫┫ ┃┫┫ ┆
┆   ┗┻┛ ┗┻┛ ┆
************************************************ */


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值