快速乘总结

 

 快速乘总结【转】

快速乘

因为我们知道乘法有的时候会溢出,及时是 longlonglonglong 也可能在乘法时爆掉。所以我们寻找一种能高效完成乘法操作并且不会爆 longlonglong  long 的算法,也就是快速乘。

1.复杂度为 O(log)O(log) 的快速乘:

我们知道乘法其实就是把很多个加法运算合到一起。现在我们的乘法会爆范围,那我们就把它转化为加法。但是我们不可能一个一个的加,这样复杂度会是 O(n)O(n) 级别。所以我们模仿2进制加法操作来完成。

inline ll ksc(ll x,ll y,ll p){//计算x乘y的积
    ll res=0;//加法初始化
    while(y){
        if(y&1)res=(res+x)%p;//模仿二进制
        x=(x<<1)%p; y>>=1;//将x不断乘2达到二进制
    }return res;
}
// ll 表示 long long

 

当然我们不一定要仿照2进制,也可以是其他进制,只要中间算每一位上数字代表值时不会爆 longlonglonglong 就行!

2.优秀的结构:__int128

__int128是c++自带的一个数据类型,顾名思义,它可以装下 21282128 级别的大数据,而且可以直接进行各种加减乘除之类的操作(复杂度很接近 O(1)O(1) ),不过它需要手写输出(但其实我们只需要在运算时用一下就可以了,就像下面这样:)

long long ans=((__int128)x*y)%p

 

还有一点遗憾的就是:联赛中基本上不会允许使用这个数据类型的

3.非常优秀的 O(1)O(1) 快速乘

这个东西个人感觉很不靠谱,但它就是能算出来正确答案。它就是用long double 来进行优化取模运算。让我们先看一代码实现吧:

inline ll ksc(ll x,ll y,ll p){
    ll z=(ld)x/p*y;
    ll res=(ull)x*y-(ull)z*p;
    return (res+p)%p;
}
// ll 表示 long long
// ld 表示 long double
// ull 表示 usigned long long
// 一种自动溢出的数据类型(存满了就会自动变为0)

 

看到这份代码有没有感到十分奇怪? 它中间是直接用了乘法操作的啊!这不直接爆掉了吗?

但是它就是可以算出正确答案来。因为它其实很巧妙的运用了自动溢出这个操作,我们的代码中的z就表示 x×y/p⌊x×y/p⌋ ,所以我们要求的就变成了 x×yx×y/p×px×y−⌊x×y/p⌋×p ,虽然这两个部分都是会溢出的,但(unsigned)保证了它们溢出后的差值基本不变,所以即使它会溢出也不会影响最终结果的!

关于快速乘的灵活转化:

我们知道快速乘的原理其实就是乘法转加法,但是这是可以根据题目性质灵活转变的,我们如何转成加法决定了我们的复杂度,就像如果模数并没有超过int范围很多,那我们适当的运用乘法分配律可以让复杂度极低:

inline ll ksc(ll x, ll y, ll P){
    ll L=x*(y>>25)%P*(1<<25)%P;
    ll R=x*(y&((1<<25)-1))%P;
    return (L+R)%P;
}

 

在保证运算不会爆long long的前提下,我们可以尽量优化其复杂度,就像上述代码在模数小于 10121012 的情况下完全变成了 O(1)O(1) 级别,在某些题目中会十分优秀!


 ✐☎博主(✐wch✎)撰文不易,转载还请注明出处;若对本文有疑,请私信或在下方讨论中提出。O(∩_∩)O谢谢!☏


☃〔尽管小伙伴们肯定有千百种方式针对,但博主还是极其非常十分不要脸的把反对键吃掉辣!〕☃

✿『AtAt lastlast :非常一(hu)本(shuo)正(ba)经(dao)的:博主很笨,请不要欺负他』✿✍

原博:✐wch✎
 



posted @ 2019-08-27 11:41  QUEKI嶺冬  阅读(211)  评论(0)    收藏  举报
/*! Color themes for Google Code Prettify | MIT License | github.com/jmblog/color-themes-for-google-code-prettify */ .pln{color:#4d4d4c}ol.linenums{margin-top:0;margin-bottom:0;color:#8e908c}li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{padding-left:1em;background-color:#fff;list-style-type:decimal!important;}@media screen{.str{color:#718c00}.kwd{color:#8959a8}.com{color:#8e908c}.typ{color:#4271ae}.lit{color:#f5871f}.pun{color:#4d4d4c}.opn{color:#4d4d4c}.clo{color:#4d4d4c}.tag{color:#c82829}.atn{color:#f5871f}.atv{color:#3e999f}.dec{color:#f5871f}.var{color:#c82829}.fun{color:#4271ae}} /*下面是我设置背景色,字体大小和字体*/ .cnblogs-markdown code{ background:#fff!important; } .cnblogs_code,.cnblogs_code span,.cnblogs-markdown .hljs{ font-size:16px!important; } .syntaxhighlighter a, .syntaxhighlighter div, .syntaxhighlighter code, .syntaxhighlighter table, .syntaxhighlighter table td, .syntaxhighlighter table tr, .syntaxhighlighter table tbody, .syntaxhighlighter table thead, .syntaxhighlighter table caption, .syntaxhighlighter textarea { font-size: 16px!important; } .cnblogs_code, .cnblogs_code span, .cnblogs-markdown .hljs{ font-family:consolas, "Source Code Pro", monaco, monospace !important; } //以上是代码高亮 /* 文字特效 */