(题面来自luogu)

题目描述

输入两个正整数a和b,求a^b的所有因子之和。结果太大,只要输出它对9901的余数。

输入格式

仅一行,为两个正整数a和b(0≤a,b≤50000000)。

输出格式

a^b的因子和对9901的余数。

  题中给出的数据很大,暴力明显不可取。顺着题目的思路,我们需要表示出a^b的所有约数之和。考虑把a质因数分解,则原式可以表示为:

  

  那么上式的所有因数就是它的质因数的组合相乘构成的集合。令它们求和,可以发现,和式可以因式分解后表示为

  

  这个式子把所求的答案表示成了若干和式相乘的形式,可以较为方便的进行取模。而前9个质数之积已经超过了给定范围,原式的乘数不会很多,因此把每个和式的答案算出来暴力相乘即可。

  观察发现每个和式都是等比数列求和的形式;如果直接套用公式,需要做除法,可以使用费马小定理求出每个除数的逆元来做。因为我觉得逆元很麻烦,这里依照算法进阶的思路,使用分治在log^2的复杂度内求出每个和式的结果。当ci * b为奇数时:

  

  这个式子每进行一次分解,和式的项数就会缩小一半,很适合进行分治计算;式中提出的p的幂可以用快速幂来算出。当ci * b是偶数时,可以提出一个p来变为奇数处理。那么等比数列求和也可以在可承受的复杂度内解决了。

  本题的总体思路:质因数分解a^b,把所求因数和因式分解为每个质因数的若干次幂等比求和相乘的形式后,分治递归求出每一个等比数列的和。

代码:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cstdio>
  5. using namespace std;
  6. const int mod(9901), msqrt(7100), maxn(50000000);
  7. int A, B;
  8. int prime[msqrt];
  9. bool vis[msqrt];
  10. void euler() {  //欧拉筛
  11. for (int i = 2; i <= msqrt; ++i) {
  12. if (!vis[i])
  13. prime[++prime[0]] = i;
  14. for (int j = 1; j <= prime[0] && prime[j] * i <= msqrt; ++j) {
  15. vis[prime[j] * i] = true;
  16. if (i % prime[j] == 0)
  17. break;
  18. }
  19. }
  20. /*  int t = 1;
  21. for (int i = 1; i <= prime[0]; ++i) { //暴力确定质因数的最多个数
  22. t *= prime[i];
  23. if (t > maxn) {
  24. cout << i << " " << t;
  25. break;
  26. }
  27. }*/
  28. }
  29. int fc[20][2], top;
  30. void Get_factors(int x, const int &B) {  //质因数分解
  31. for (int i = 1; i <= prime[0] && x; ++i)
  32. if (x % prime[i] == 0) {
  33. fc[++top][0] = prime[i];
  34. while (x % prime[i] == 0)
  35. ++fc[top][1], x /= prime[i];
  36. fc[top][1] *= B;
  37. }
  38. if (x > 1)//A is a big prime
  39. fc[++top][0] = x, fc[top][1] = B;
  40. }
  41. int ans = 1;
  42. int fpow(int a, int b) {
  43. int ret = 1;
  44. while (b) {
  45. if (b & 1)
  46. ret = ret * a % mod;
  47. b >>= 1;
  48. a = a * a % mod;
  49. }
  50. return ret;
  51. }
  52. int calc(int a, int b) {  //计算各等比数列之和
  53. if (b == 0) return 1;
  54. if (b & 1)
  55. return (1 + fpow(a, (b + 1) >> 1)) * calc(a, b >> 1) % mod;
  56. return (1 + a * calc(a, b - 1)) % mod;
  57. }
  58. int main() {
  59. cin >> A >> B;
  60. if (A == 0) {  //特判
  61. putchar('0');
  62. return 0;
  63. }
  64. euler();
  65. Get_factors(A, B);
  66. for (int i = 1; i <= top; ++i)
  67. ans = (ans * calc(fc[i][0] % mod, fc[i][1])) % mod;
  68. cout << ans;
  69. return 0;
  70. }

【POJ 1845】Sumdiv——数论 质因数 + 分治 + 快速幂的更多相关文章

  1. poj 1845 Sumdiv (数论)

    题目链接 题意:求 A^B的所有约数之和对9901取模后的结果. 分析: 看了小优的博客写的. 分析来自 http://blog.csdn.net/lyy289065406/article/detai ...

  2. poj 1845 POJ 1845 Sumdiv 数学模板

    筛选法+求一个整数的分解+快速模幂运算+递归求计算1+p+p^2+````+p^nPOJ 1845 Sumdiv求A^B的所有约数之和%9901 */#include<stdio.h>#i ...

  3. poj 2888 Magic Bracelet(Polya+矩阵快速幂)

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4990   Accepted: 1610 D ...

  4. 【BZOJ4002】[JLOI2015]有意义的字符串(数论,矩阵快速幂)

    [BZOJ4002][JLOI2015]有意义的字符串(数论,矩阵快速幂) 题面 BZOJ 洛谷 题解 发现我这种题总是做不动... 令\(A=\frac{b+\sqrt d}{2},B=\frac{ ...

  5. 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)

    [BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...

  6. POJ 1845 Sumdiv [素数分解 快速幂取模 二分求和等比数列]

    传送门:http://poj.org/problem?id=1845 大致题意: 求A^B的所有约数(即因子)之和,并对其取模 9901再输出. 解题基础: 1) 整数的唯一分解定理: 任意正整数都有 ...

  7. POJ 1845 Sumdiv (整数拆分+等比快速求和)

    当我们拆分完数据以后, A^B的所有约数之和为: sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...*[1+pn+pn^2 ...

  8. poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】

    POJ 1845 题意不说了,网上一大堆.此题做了一天,必须要整理一下了. 刚开始用费马小定理做,WA.(poj敢说我代码WA???)(以下代码其实都不严谨,按照数据要求A是可以等于0的,那么结果自然 ...

  9. POJ 1845 Sumdiv

    快速幂+等比数列求和.... Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 12599 Accepted: 305 ...

随机推荐

  1. exe打包成安装文件(界面美观)

    前言 在开发windows桌面应用过程中,软件交付时,一般都是交付安装包. 安装文件的优点 显得更正规,安装界面也可展示软件特点介绍,可自动生成桌面图标等: 安装包体积要比软件小,方便下载. 探索之路 ...

  2. array_walk_recursive 地址引用报错的问题

    今天看十八哥的视频,学习array_walk_recursive的用法,发现一直报错: PHP版本:5.6.19 代码界面: 报错界面: 查了很长时间,不知道什么问题,后来在网上终于找到原因所在: + ...

  3. NB-IoT的HARQ过程是怎么样的

    NB-IoT的HARQ是一种将前向纠错(Forward Error Correction,FEC)编码和ARQ相结合而形成的技术.HARQ的基本原理是缓存没有正确接收到的数据,并且将重传数据和原始数据 ...

  4. Spring创建Bean的过程Debug

    目录 Spring流程Debug 1.1 Spring测试环境搭建 1.2 Debug容器创建过程 1.3 AbstractApplicationContext的refresh()包含的13个方法分析 ...

  5. 一次 KVM 虚拟机磁盘占满的排查过程

    一次 KVM 虚拟机磁盘占满的排查过程 KVM 虚拟机系统为 CentOS,文件系统为 XFS. 现象如下: 使用 df -h 命令发现磁盘剩余空间为30k(总大小为30G),使用 df -i 发现 ...

  6. 【Azure 环境】存储在Azure上的文件,使用IE/Edge时自动打开的问题,如何变为下载而非自动打开

    问题描述 存储,作为云服务最重要的一部分.当需要从云存储中下载文件时,时常面临一些格式的文件被浏览器自动打开而非下载,那如何来解决这个问题呢? 在Azure中,存储的服务有以下方式: Azure Bl ...

  7. 寻找性能更优秀的动态 Getter 和 Setter 方案

    反射获取 PropertyInfo 可以对对象的属性值进行读取或者写入,但是这样性能不好.所以,我们需要更快的方案. 方案说明 就是用表达式编译一个 Action<TObj,TValue> ...

  8. php 批量脚本检测语法错误

    shell 根据参数检测 当前php项目下 的语法错误 #!/bin/bash function getdir(){ for el in `ls $1` do dir_file=$1"/&q ...

  9. [MIT6.006] 21. Daynamic Programming III: Parenthesization, Edit Distance, Knapsack 动态规划III:括号问题,编辑距离,背包问题

    这节课主要针对字符串/序列上的问题,了解如果使用动态规划进行求解.上节课我们也讲过使用前缀和后缀的概念,他们如下所示: 接下来,我们通过三个问题来深入了解下动态规划使用前缀.后缀和子串怎么去解决括号问 ...

  10. exec 家族库函数以及系统调用(execl,execle,execlp and execv,execvp,execve)

    (1)exec函数说明 fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法.它可以根据指定的 ...