题目链接:http://poj.org/problem?id=1845

 

思路:

1.整数唯一分解定理:

      任意正整数都有且只有一种方式写出其素因子的乘积表达式。

      a=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   其中pi均为素数

2.约数和公式:

  对于已经分解的整数a=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)

  有a的所有因子之和为

     S` = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)

那么 a^b 的所有因子和为

  S = (1+p1+p1^2+p1^3+...p1^(k1*b)) * (1+p2+p2^2+p2^3+….p2^(k2*b)) * (1+p3+ p3^3+…+ p3^(k3*b)) * .... * (1+pn+pn^2+pn^3+...pn^(kn*b))

对于数列 1, p, p^2, p^3 ...  p^n % mod,其中  mod 为质数,打个表可以发现该数列是一个循环数列,其中存在一个循环节为 1, p, p^1, ... p^(mod-2).其实这点在费马小定理中是有体现的,a^(mod-1) = 1 (% mod).

那么对于求 cnt = 1 + p + p^2 + ... + p^n % mod,可以令

  cc1 = (n + 1) / (mod - 1)

  cc2 = (n + 1) % (mod - 1)

  cnt1 = 1 + p + p^2 + ... + p^(mod - 2)

  cnt2 = 1 + p + p^2 + ... + p^(cc2 - 1)

那么 cnt = cc1 * cnt1 + cnt2 % mod

对于求 a^b,可以先将 a 质因分解,得到 S 的表达式,对于 S 表达式,只需要按照上面的方法求出其中每个乘数项即可.时间复杂度为 O(loga * mod), 本题中 mod = 9901, 时间上是允许的.

 

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <map>
 4 #define ll long long
 5 using namespace std;
 6 
 7 const int mod = 9901;
 8 const int MAXN = 1e5 + 10;
 9 ll prime[MAXN], indx = 0;
10 map<int, int> num;
11 
12 int get(ll a, ll b){//计算sigma(a^i),其中0<=i<=b
13     ll sol1 = 0, sol2 = -1, cnt = 1;
14     ll cc1 = (b + 1) / (mod - 1);
15     ll cc2 = (b + 1) % (mod - 1);
16     for(int i = 0; i < mod - 1; i++){
17         sol1 = (sol1 + cnt) % mod;
18         if(sol2 == -1 && i + 1 == cc2) sol2 = sol1;
19         cnt = (cnt * a) % mod;
20     }
21     return (sol1 * cc1 % mod + sol2) % mod;
22 }
23 
24 int main(void){
25     ll a, b, sol = 1;
26     cin >> a >> b;
27     for(int i = 2; i * i <= a; i++){
28         if(a % i == 0){
29             prime[indx] = i;
30             while(a % i == 0){
31                 num[i]++;
32                 a /= i;
33             }
34             indx++;
35         }
36     }
37     if(a > 1) prime[indx++] = a, num[a]++;
38     for(int i = 0; i < indx; i++){
39         sol = (sol * get(prime[i], b * num[prime[i]])) % mod;
40     }
41     cout << sol << endl;
42     return 0;
43 }
View Code

相关文章: