(题面来自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. Longest common subsequence(LCS)

    问题 说明该问题在生物学中的实际意义 Biological applications often need to compare the DNA of two (or more) different ...

  2. Scrapy加Redis加IP代理池实现音乐爬虫

    音乐爬虫 关注公众号"轻松学编程"了解更多. 目的:爬取歌名,歌手,歌词,歌曲url. 一.创建爬虫项目 创建一个文件夹,进入文件夹,打开cmd窗口,输入: scrapy star ...

  3. Linux杂谈:进程锁核+实时线程导致的读写锁死循环

    发现问题 公司项目测试的时候,发现运行一段时间后会出现cpu百分之百的情况. 想着可能是哪里出现了死循环,于是打算用gdb跟一下,结果gdb居然无法attach到进程...... 定位问题 查了查去, ...

  4. 实用fork/join框架提升程序效率

    实用fork/join框架提成程序效率 原文地址:https://www.jianshu.com/p/9ce243796d4a 业务场景 最近再做一个接口,我是一个中央的消息接受方,当我接受到消息后要 ...

  5. Dorado download注意事项

    uploader/uploader-SNAPSHOT uploader/uploader-RELEASE .....使用需要注意!

  6. 服务器断电导致的ORACLE异常 : ORA-00214 ORA-01033 ORA-01034 ORA-00172 ORA-27101

    工作环境中的集群迁移之后,oracle出了挺多问题,最开始一直没找到原因,后来发现做迁移的人是冷迁移的,且数据库节点是硬关机的,惊了( 表现症状有不能登陆,登录了不能操作等 第一个报的是 ORA-00 ...

  7. 归档空间满了 导致Imp卡住

    今天在使用exp imp将生产环境数据库导入到测试环境的过程中,imp的时候 发现在导入某张表的时候卡住了. 起初是以为该表比较大的缘故,后来过了很久 发现还是卡在那里. 最后分析原因 发现设置的归档 ...

  8. vue 格式化日期

    cnpm install moment --save 摘自:https://www.cnblogs.com/zwq20134/p/11718034.html <el-table-column l ...

  9. mysql优化之2--索引优化

    1. 创建联合索引时,要注意,离散度大的列前置. 可以通过 select count(distinct(A)),count(distinct(B)) from tb; 看哪个列离散度大. 2. 索引列 ...

  10. sendfile zero-copy

    传统read/write进行网络文件传输过程当中,文件数据实际上经过四次copy操作: 硬盘->内核buf->用户buf->socket相关缓冲区->协议引擎 而sendfil ...