题解 P2613 【【模板】有理数取余】

简介: 题目链接 我们先看这个式子:$c=\dfrac{a}{b}$ $ $ $ $ $mod$ $ $ $ $ $19260817$某正常高中生:这$……$---对于这个 $c$ 。显然,它很可能是小数。那么, $double$ 的取余你老师讲过么$?!!!$所以,我们要~~化简~~魔改一下这个式子。

题目链接

我们先看这个式子:

$c=\dfrac{a}{b}$ $ $ $ $ $mod$ $ $ $ $ $19260817$

某正常高中生:这$……$

---

对于这个 $c$ 。

显然,它很可能是小数。

那么, $double$ 的取余你老师讲过么$?!!!$

所以,我们要~~化简~~魔改一下这个式子。

---

$$c=\dfrac{a}{b}=a*b^{-1}$$

又因为是 $mod$ $ $ $p=19260817$ 的意义下的计算。

所以,现在就有了一种化小数为整数的方法:

 乘法逆元

$c=a*b^{-1}≡a*b^{p-2}$ $ $ $ $ $ mod $ $ $ $ $ $ p $

而在这里, $ p $ $ = $ $ 19260817 $

并且,当 $b^{p-2}≡0$ $ $ $ $ $ mod $ $ $ $ $ $ p $ 时,

分母为 $0$ ,无解。

所以答案就出来了。

---

好了,天真的认为我~~们~~以为这样就行了。

然而$……$

$0≤a,b≤10^{10001}$

高精模低精按位先模到 $int$ 或 $long$ $ $ $ long$ 以内,在做。

然后调了三天终于$A$了。

---

本宝宝在这里在吐槽一番:

定义变量忘了初始化$……$

数据出锅玄学$RE$ $……$

也是没谁了。

---

上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int p=19260817;
int a[10100];
int b[10100];
char a1[10100];
char b1[10100];
int l1,l2;
int len1,len2;
long long x,y;

long long pow2(long long a,long long b)
{
    long long res=1;
    for(;b;b>>=1,a=a*a%p) if(b&1) res=res*a%p;
    return res%p;
}

void calculet_1()
{
    long long num=0;
    for(int i=len1;i<=len1+8;i++)
        num*=10,num+=a[i];

    num%=p;
    for(int i=len1+8;i>=len1;i--)
    {
        int now=num%10;num/=10;
        a[i]=now;
    }

    for(int i=0;i<=8;i++) if(a[len1+i]!=0){len1+=i;break;}
}

void calculet_2()
{
    long long num=0;
    for(int i=len2;i<=len2+8;i++)
        num*=10,num+=b[i];
    num%=p;
    for(int i=len2+8;i>=len2;i--)
    {
        int now=num%10;num/=10;
        b[i]=now;
    }

    for(int i=0;i<=8;i++) if(b[len2+i]!=0){len2+=i;break;}
}

signed main()
{
//    freopen("testdata.in","r",stdin);
//    freopen("1.out","w",stdout);

    scanf("%s",a1);
    scanf("%s",b1);
//    printf("%s\n",b1);
    l1=strlen(a1);
    l2=strlen(b1);//输入以及处理数据。

    for(int i=0;i<l1;i++)
      a[i]=a1[i]-'0';
    for(int i=0;i<l2;i++)
      b[i]=b1[i]-'0';//将char 变int(个人不习惯用char做运算)
    
    while(l1-len1>=10) calculet_1();
    while(l2-len2>=10) calculet_2();//计算,我是从高位到低位依次减的,可以省时间。

    for(int i=len1;i<l1;i++) x*=10,x+=a[i];
    for(int i=len2;i<l2;i++) y*=10,y+=b[i];
    x%=p;y%=p;//计算取模之后的值。
    
//    printf("%lld\n",y);
    if(x==0){puts("0");return 0;}
    if(y==0){puts("Angry!");return 0;}//特判

    long long ans=pow2(y,p-2);
//    printf("%lld\n",ans);
    ans=(ans*x)%p;

    printf("%lld",ans);//计算答案和输出
    return 0;//程序拜拜
}

 

相关文章
|
8月前
|
存储 算法
算法题解-除自身以外数组的乘积
算法题解-除自身以外数组的乘积
|
8月前
leetcode-372:超级次方(快速幂的实现以及取余的规则和推导)
leetcode-372:超级次方(快速幂的实现以及取余的规则和推导)
56 0
|
算法
剑指Offer - 面试题16:数值的整数次方
剑指Offer - 面试题16:数值的整数次方
64 0
|
机器学习/深度学习 C++
|
C语言
C语言题解——除自身以外数组的乘积(力扣 第238题)
这是力扣题库中的一个中等难题,说是存在一个整型数组,求出各元素位上除此数外其他元素的乘积,比如存在数组[1,2,3,4],按照题目应该该输出[24,12,8,6],我们的解题思想为:求出各元素的左积和右积(当然不包含自己),然后将左积与右积相乘,就可以得到目标积数,拿上面的例子来说,下标0的左积为1(默认数组外为1),右积为24,相乘得到目标积24,其他元素也是依次类推。下面来看看具体讲解吧
182 0
C语言题解——除自身以外数组的乘积(力扣 第238题)
|
存储 算法
【每日挠头算法题】Leetcode 989. 数组形式的整数加法 —— 高精度加法解法
【每日挠头算法题】Leetcode 989. 数组形式的整数加法 —— 高精度加法解法
156 0
【每日挠头算法题】Leetcode 989. 数组形式的整数加法 —— 高精度加法解法
|
存储 算法 Go
【刷题】两数相加
【刷题】两数相加
107 0
【刷题】两数相加
|
存储 算法 前端开发
力扣- 415. 字符串相加 🧶
力扣- 415. 字符串相加 🧶
121 0
|
C++ Python
有趣的数学推导题目-leetcode462. 最少移动次数使数组元素相等 II
有趣的数学推导题目-leetcode462. 最少移动次数使数组元素相等 II