数学技巧

数学技巧

题目

题目

  • 越狱

    \(简析\) 既然顺着题目想 很困难, 是否可以 "逆向"思维?

    ​ 答案为: \(m^n - m(m-1)^{n-1}\)

    AC代码 注意: \((a-b)\bmod p\) 在实现上应写成 \((a-b+p)\bmod p\)

快速幂

求 \(a^b\) .  由于 \(b=c_{k-1}2^{k-1} + c_{k-2}2^{k-2}+...+c_02^0\), 其中 \(k=\lceil log(b+1)\rceil\)​(b在二进制下的位数)

我们可以递推.

int qpow(int a, int b){
    a%=MOD;							// 别漏了~
	int res=1;
	while(b){
		if(b&1) res=(res*a)%MOD;	// 若MOD略大, 这里可能需要转 long long
		a=(a*a)%MOD; b>>=1;
	}
	return res;
}

速乘

由于乘法可能会爆 long long, 比如 快速幂中的乘法, 如果 MOD很大(比如为INT_MAX) 就很有可能爆long long.
写 高精度? 太麻烦了, 不仅容易出错, 还效率很低.   
于是有了如下两个速乘: 龟速乘和快速乘

龟速乘 \(O(log\ b)\)

与快速幂原理大同小异.

ll smul(ll a, ll b, ll P){
    ll res=0;
    while(b){	
		if(b&1) res=(res+a)%P;
        a=(a+a)%P; b>>=1;
    }
    return res;
}

快速乘 \(O(1)\)

核心为: \(ab\bmod p = ab-\lfloor ab/p\rfloor p\)​  记 \(c=\lfloor ab/p\rfloor\)​

  • 求 c: 用 浮点数直接计算 \(ab/p\), 当浮点数精度不足以保存精确数值时, 它会舍弃低位.

    long double 在十进制下的有效数字为 18~19 位, 而 若 \(a,b<p\)​​ 则 c 也在18位以内. 可以用long double 来存 c

  • 值得一提的是: 若 \(p\mid ab\)​ , 则由于精度误差, 算出的c可能比实际小1, 但在取模意义下并不影响结果的正确性

  • 由于\(ab-cp = ab\bmod p\)​, 且\(ab-cp≤p<2^{64}\) 所以\(ab-cp=(ab-cp)\bmod 2^{64}\) !

    unsigned long long自然溢出进行模数

ull qmul(ull a, ull b, ull p){
	a%=p, b%=p;
    ull c=(long double) a*b/p
    ull x=a*b, y=c*p;
    ll res=(ll)(x%p) - (ll)(y%p);	//这里的括号不要漏掉了
    if(res<0) res+=p;				//不要漏掉了.
    return res;
}
上一篇:图文讲解Freehand常用特色功能


下一篇:uni-app开发企微H5——推送消息给客户