zoukankan      html  css  js  c++  java
  • POJ1845 Sumdiv 数论

    求一个数形如 A^B 的所有因子和对9901的模。

    我们首先得到A的素因子分解形式p1^e1*p2^e2...pn^en 它的B次方就是p1^E1*p2^E2...pn^En,其中Ei = ei*B。其素因子的和就是(p1^0+p1^2+p1^3+...+p1^E1)*(p2^0+p2^2+p2^3+...+p2^E2)*... 对于其中的一项进行二分计算即可。注意大质数的存在。

    代码如下:

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <map>
    #include <queue>
    #include <vector>
    #include <stack>
    #include <list>
    #include <set>
    #define MOD 9901
    using namespace std;
    
    int A, B, fac[7100], rec[7100], idx;
    int remain;
    
    int _pow(int a, int b) {
        int ret = 1;
        while (b) {
            if (b & 1) {
                ret *= a;
                ret %= MOD;    
            }    
            a *= a;
            a %= MOD;
            b >>= 1;
        }
        return ret;
    }
    
    int Ac(int x, int y) {
        int temp, ret;
        if (!y) return 1;
        if ((y+1) & 1) { // 如果有奇数项 
            temp = Ac(x, (y>>1)-1);
            ret = temp + temp*_pow(x, y>>1)%MOD + _pow(x,y);
            ret %= MOD;
        } else {
            temp = Ac(x, y>>1);
            ret = temp + temp*_pow(x, (y>>1)+1);
            ret %= MOD;
        }
        return ret;
    }
    
    int main()
    {
        int sqt, ret;
        while (scanf("%d %d", &A, &B) == 2) {
            if (!A) {
                puts("0");
                continue;    
            }
            if (A == 1) {
                puts("1");
                continue;
            } // 对以上两个情况进行特判
            idx = remain = -1;
            ret = 1;
            sqt = (int)sqrt(double(A));
            memset(fac, 0, sizeof (fac));
            for (int i = 2; i <= sqt; ++i) {
                if (A % i == 0) {
                    rec[++idx] = i;
                    while (A % i == 0) {
                        ++fac[i];
                        A /= i;
                    }
                    fac[i] *= B;
                }
            }
            if (A != 1) remain = A;
            for (int i = 0; i <= idx; ++i) {
                ret *= Ac(rec[i]%MOD, fac[rec[i]]);
                ret %= MOD;
            }
            if (remain != -1) {
                ret *= Ac(remain%MOD, B);
                ret %= MOD;
            }
            printf("%d\n", ret);
        }
        return 0;
    }
  • 相关阅读:
    【Jsoi2010】连通数
    【CQOI2009】中位数图
    【POJ 1151】 Altlantis
    【2017省中集训】 香港记者
    【AHOI2009】中国象棋
    【SCOI 2009】 Windy数
    【HDU 4722】 Good Numbers
    【HDU 2089】 不要62
    BZOJ3129 SDOI2013方程(容斥原理+扩展lucas)
    BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)
  • 原文地址:https://www.cnblogs.com/Lyush/p/2683116.html
Copyright © 2011-2022 走看看