POJ1995:Raising Modulo Numbers

二进制前置技能:https://www.cnblogs.com/AKMer/p/9698694.html

题目传送门:http://poj.org/problem?id=1995

题目就是求\(\sum_{i=1}^na[i]^{b[i]}mod\) \(m\)。我们只要会快速求\(a^b\)就行了。

我们可以用二进制拆分思想,把\(a^b\)转化成\(a^{(1010...1)_2}\)之类的。然后根据\(a^{x+y}=a^x*a^y\),我们可以将\(a^b\)转化成\(a^{(10000)_2}*a^{(100)_2}*a^{(1)_2}\)之类的形式。当二进制下这一位为\(1\),我们就把它累乘进答案里。

有因为\(a^{2x}=a^x*a^x\),所以对于每一位表示下\(a^{(100..)_2}\),我们可以通过上一位的平方得来。

所以二进制下有多少位,我们就进行多少次运算。

时间复杂度:\(O(nloga)\)

空间复杂度:\(O(1)\)

代码如下:

#include <cstdio>
using namespace std;

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

int quick(int x,int y,int m) {
    int sum=1;
    while(y) {
        if(y&1)sum=1ll*sum*x%m;//如果y的二进制当前位置为1,就把x累乘进去
        x=1ll*x*x%m;y>>=1;//否则x平方,y右移一位
    }
    return sum;
}

int main() {
    int Z=read();
    while(Z--) {
        int ans=0,m=read(),n=read();
        for(int i=1;i<=n;i++) {
            int x=read(),y=read();
            ans=(ans+quick(x,y,m))%m;//累加求答案
        }printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKMer/p/9698850.html