题解 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;//程序拜拜
}

 

相关文章
|
4天前
|
存储
【力扣】2. 两数相加、445. 两数相加Ⅱ
【力扣】2. 两数相加、445. 两数相加Ⅱ
|
3月前
leetcode-372:超级次方(快速幂的实现以及取余的规则和推导)
leetcode-372:超级次方(快速幂的实现以及取余的规则和推导)
23 0
|
7月前
|
存储
每日一题(两数相加)
每日一题(两数相加)
|
10月前
剑指offer 73. 不用加减乘除做加法
剑指offer 73. 不用加减乘除做加法
42 0
|
存储 算法
【每日挠头算法题】Leetcode 989. 数组形式的整数加法 —— 高精度加法解法
【每日挠头算法题】Leetcode 989. 数组形式的整数加法 —— 高精度加法解法
117 0
【每日挠头算法题】Leetcode 989. 数组形式的整数加法 —— 高精度加法解法
|
Python
LeetCode 989. 数组形式的整数加法
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组。
85 0
|
C语言
写一个计算器(C语言版本),可以求出:整数的加,减,乘,除四则运算
写一个计算器(C语言版本),可以求出:整数的加,减,乘,除四则运算
164 0
写一个计算器(C语言版本),可以求出:整数的加,减,乘,除四则运算
LeetCode每日一题——592. 分数加减运算
给定一个表示分数加减运算的字符串 expression ,你需要返回一个字符串形式的计算结果。
88 0
108.递归整数四则运算
108.递归整数四则运算
60 0
2015年蓝桥杯 题7 加法变乘法 列举 (提交整数)
2015年蓝桥杯 题7 加法变乘法 列举 (提交整数)