CH0102 64位整数乘法 数论

时间:2022-12-12 08:35:20

正解:数论/一个神仙想法

解题报告:

先放传送门qwq

两种方法,都还挺妙的就都写了qwq

第一种是快速幂

把b用二进制表示成,ck*2k+ck-1*2k-1+...+c0*20

然后就可以表示成,a*(ck*2k+ck-1*2k-1+...+c0*20)%p

然后就可以用快速幂的思想做掉,能理解趴?

哦其实也可以用秦九韶理解,差不多,反正都这个意思就是了qwq

#include<bits/stdc++.h>
using namespace std;
#define rp(i,x,y) for(register ll i=x;i<=y;++i)
#define ll unsigned long long

ll a,b,p;

inline ll read()
{
    ;;
    '))ch=getchar();
    ;
    )+(x<<)+(ch^'),ch=getchar();
    return y?x:-x;
}
inline ll js(ll x,ll y,ll mod)
{
    ll ans=;
    while(x)
    {
        )ans+=y,ans%=mod;
        x>>=;y<<=;y%=mod;
    }
    return ans;
}

int main()
{
    a=read(),b=read(),p=read();
    printf("%lld\n",js(a,b,p));
    ;
}

第二种是一个,神仙想法

首先很容易能理解就是 a*b%p=a*b-⌊a*b/p⌋*p

然后就可以分成俩部分计算,一个是a*b直接算一个是⌊a*b/p⌋*p

首先理解一个东西,就是因为%p所以答案一定是小于等于p的,那么溢出导致舍弃掉了的部分就没有关系反正本来就是太大了要被废掉的

然后另一个就是⌊a*b/p⌋*p,我们可以先开个double算出⌊a*b/p⌋,考虑精度不够怎么办?没有关系因为double有效数字就是18-19的样子(,,,就是这么巧,被出题人安排得明明白白×)所以舍弃掉的部分刚好就是我们不需要的部分

然后就欧克了

是不是很妙!!!

(然后我开始做的时候还WA了一下,,,解释下发生了什么qwq就是,a和b是要%p的然后我忘了,,,所以就WA了,估计是溢出之类的问题?虽然我本机是A的?真实哭泣QAQ

#include<bits/stdc++.h>
using namespace std;
#define rp(i,x,y) for(register ll i=x;i<=y;++i)
#define ll unsigned long long

ll a,b,p,cjk;
double goldgenius;

inline ll read()
{
    ;;
    '))ch=getchar();
    ;
    )+(x<<)+(ch^'),ch=getchar();
    return y?x:-x;
}

int main()
{
    a=read(),b=read(),p=read();
    cjk=a*b;goldgenius=(double)a*b/p;
    cjk=cjk-(ll)goldgenius*p;cjk%=p;)cjk+=p;
    printf("%lld\n",cjk);
    ;
}

umm然后留下一个傻逼问题(,,,其实开始困扰了我半天来着×),这样的

为什么不可以直接算a*b%p呢?

这是因为!可能你舍掉了高位之后膜p会有问题!能懂趴?然后用法二就可以巧妙避免这个问题!

好那这题就解决辣!