HDU 1852 快速求幂

来源:互联网 发布:cad2016for mac汉化包 编辑:程序博客网 时间:2024/05/17 04:18

题目wa了好多回..悲催...不能直接求逆元来计算,还是要用到数论中的小技巧啊...

贴神牛的题解吧..

// 这题主要求S
// 结论: S = (251^(n+1)-1) * (2^(3n+1)-1) / 250
// 是两个等比数列和相乘
//
// 推理:
// 2008 = 2^3 * 251
// 所以 2008^N 有 3N 个 2 和 N 个251
// 所有仅由2组成的因子有
// 2^0 2^1 2^2 ... 2^(3N)
// 设集合 C = {2^0, 2^1, 2^2 ...,2^(3N)};
// SUM(C) = 2^(3n+1)-1

// 跟251组合产生的因子有
// 251^0 * C
// 251^1 * C
// ...
// 251^N * C

// 所有因子和为:
// S = (251^(n+1)-1))/250 * (2^(3n+1)-1)

// 计算S%K:

// S 很大, 不能保存在普通的数据类型中, 需要直接计算S%K
// 因为S有个分母250, 设 S = X/250
// 则  S%K = (X/250)%K = (X%(250*K))/250
// 变成先求余数再除法的形式

知道了数论中的技巧,不能用你逆元来求哇,因为不满足gcd(250,k )或者gcd(2,k)不一定是互质的, 代码就不是再是问题了,

 

#include<stdio.h>
int mult(int a1,int n,int k){
    if(n==0) return 1;
    __int64 b=1,a = a1;
    while(n>1){
        if(n%2==0) {
            a=a*a%k;
            n/=2;
        }
        else {
            b=b*a%k;
            n--;
        }
    }
    return a*b%k;
}
int main(){
    int n,k;
    while(scanf("%d%d",&n,&k),n&&k){
        __int64 a=mult(2,3*n+1,250*k);
        __int64 b=mult(251,n+1,250*k);
        a-- , b--;
        a = ( a*b )%(250*k);
        a /= 250;
        printf("%d\n",mult(2008,a,k));
    }
}