HDU-1452 因子和 积性函数性质

详见代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MOD 29
using namespace std;

/*
求2004^x次方的所有因子对29取余,可能是由于这一年是闰年才选择的29 
我们可以对2004进行分解 2004 = 2^2 * 3 * 167,很明显2^2 和 3 和 167 都是相互互质的
因此就可以利用到一个数的因子和是一个积性函数这个性质,设S(N)为这个函数 
又因为S(p^n) = 1+p+p^2+...+p^n,所以一个数被用素数的指数幂来表示的话就能够被分解化
的表示出来S(p^n) = (p^(n+1)-1)/(p-1)
{ 
    %运算法则 1. (a*b) %p= ( a%p) *(b%p)
    %运算法则 2. (a/b) %p= ( a *b^(-1)%p)
}
由上面的公式我们可以的出来S(p^n)%29 = (p^(n+1)-1)*(p-1)^(-1)%29
而x^(-1)就是x%p的逆元满足 x*inv(x) = 1%p
因子2-1=1,所以可以直接算
因子3-1=2,逆元为15,因为2*15%29=1
因子167%29=22; 22-1=21的逆元是18,因为21*18%29=1 
*/

int _pow(int a, int b) {
    int ret = 1;
    while (b) {
        if (b & 1) {
            ret *= a;
            ret %= MOD;    
        }
        b >>= 1;
        a *= a;
        a %= MOD; 
    }    
    return ret;
}

int main() {
    int N, ret; // 表示2004的N次方
    while (scanf("%d", &N), N) {
        ret = 1;
        ret *= (_pow(2, 2*N+1)-1+MOD)%MOD;
        ret %= MOD;
        ret *= ((_pow(3, N+1)*15-15)+MOD)%MOD;
        ret %= MOD;
        ret *= ((_pow(22, N+1)*18-18)+MOD)%MOD;
        ret %= MOD;
        printf("%d\n", ret);
    }
    return 0;    
}

 

posted @ 2012-12-31 22:55  沐阳  阅读(245)  评论(0编辑  收藏  举报