【POJ 1845】Sumdiv——数论 质因数 + 分治 + 快速幂
(题面来自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,把所求因数和因式分解为每个质因数的若干次幂等比求和相乘的形式后,分治递归求出每一个等比数列的和。
代码:
- #include <iostream>
 - #include <algorithm>
 - #include <cstring>
 - #include <cstdio>
 - using namespace std;
 - const int mod(9901), msqrt(7100), maxn(50000000);
 - int A, B;
 - int prime[msqrt];
 - bool vis[msqrt];
 - void euler() { //欧拉筛
 - for (int i = 2; i <= msqrt; ++i) {
 - if (!vis[i])
 - prime[++prime[0]] = i;
 - for (int j = 1; j <= prime[0] && prime[j] * i <= msqrt; ++j) {
 - vis[prime[j] * i] = true;
 - if (i % prime[j] == 0)
 - break;
 - }
 - }
 - /* int t = 1;
 - for (int i = 1; i <= prime[0]; ++i) { //暴力确定质因数的最多个数
 - t *= prime[i];
 - if (t > maxn) {
 - cout << i << " " << t;
 - break;
 - }
 - }*/
 - }
 - int fc[20][2], top;
 - void Get_factors(int x, const int &B) { //质因数分解
 - for (int i = 1; i <= prime[0] && x; ++i)
 - if (x % prime[i] == 0) {
 - fc[++top][0] = prime[i];
 - while (x % prime[i] == 0)
 - ++fc[top][1], x /= prime[i];
 - fc[top][1] *= B;
 - }
 - if (x > 1)//A is a big prime
 - fc[++top][0] = x, fc[top][1] = B;
 - }
 - int ans = 1;
 - int fpow(int a, int b) {
 - int ret = 1;
 - while (b) {
 - if (b & 1)
 - ret = ret * a % mod;
 - b >>= 1;
 - a = a * a % mod;
 - }
 - return ret;
 - }
 - int calc(int a, int b) { //计算各等比数列之和
 - if (b == 0) return 1;
 - if (b & 1)
 - return (1 + fpow(a, (b + 1) >> 1)) * calc(a, b >> 1) % mod;
 - return (1 + a * calc(a, b - 1)) % mod;
 - }
 - int main() {
 - cin >> A >> B;
 - if (A == 0) { //特判
 - putchar('0');
 - return 0;
 - }
 - euler();
 - Get_factors(A, B);
 - for (int i = 1; i <= top; ++i)
 - ans = (ans * calc(fc[i][0] % mod, fc[i][1])) % mod;
 - cout << ans;
 - return 0;
 - }
 
【POJ 1845】Sumdiv——数论 质因数 + 分治 + 快速幂的更多相关文章
- poj 1845 Sumdiv (数论)
		
题目链接 题意:求 A^B的所有约数之和对9901取模后的结果. 分析: 看了小优的博客写的. 分析来自 http://blog.csdn.net/lyy289065406/article/detai ...
 - poj 1845 POJ 1845 Sumdiv 数学模板
		
筛选法+求一个整数的分解+快速模幂运算+递归求计算1+p+p^2+````+p^nPOJ 1845 Sumdiv求A^B的所有约数之和%9901 */#include<stdio.h>#i ...
 - poj 2888 Magic Bracelet(Polya+矩阵快速幂)
		
Magic Bracelet Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 4990 Accepted: 1610 D ...
 - 【BZOJ4002】[JLOI2015]有意义的字符串(数论,矩阵快速幂)
		
[BZOJ4002][JLOI2015]有意义的字符串(数论,矩阵快速幂) 题面 BZOJ 洛谷 题解 发现我这种题总是做不动... 令\(A=\frac{b+\sqrt d}{2},B=\frac{ ...
 - 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
		
[BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...
 - POJ 1845 Sumdiv [素数分解 快速幂取模 二分求和等比数列]
		
传送门:http://poj.org/problem?id=1845 大致题意: 求A^B的所有约数(即因子)之和,并对其取模 9901再输出. 解题基础: 1) 整数的唯一分解定理: 任意正整数都有 ...
 - POJ 1845 Sumdiv (整数拆分+等比快速求和)
		
当我们拆分完数据以后, A^B的所有约数之和为: sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...*[1+pn+pn^2 ...
 - poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】
		
POJ 1845 题意不说了,网上一大堆.此题做了一天,必须要整理一下了. 刚开始用费马小定理做,WA.(poj敢说我代码WA???)(以下代码其实都不严谨,按照数据要求A是可以等于0的,那么结果自然 ...
 - POJ 1845 Sumdiv
		
快速幂+等比数列求和.... Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 12599 Accepted: 305 ...
 
随机推荐
- 【ELK】Centos7 安装 ELK 7.6.2 和 UI 管理界面以及测试例子
			
1. 初始化环境 1.0 初始化环境官网参考 https://www.elastic.co/guide/en/elasticsearch/reference/current/system-config ...
 - Luogu P4247 [清华集训2012]序列操作
			
题意 给定一个长度为 \(n\) 的序列 \(a\) 和 \(q\) 次操作,每次操作形如以下三种: I a b c,表示将 \([a,b]\) 内的元素加 \(c\). R a b,表示将 \([a ...
 - 快来,我悄悄的给你说几个HashCode的破事。
			
这是why技术的第 72 篇原创文章 Hash冲突是怎么回事 在这个文章正式开始之前,先几句话把这个问题说清楚了:我们常说的 Hash 冲突到底是怎么回事? 直接上个图片: 你说你看到这个图片的时候想 ...
 - [Luogu P2051] [AHOI2009]中国象棋 (状压DP->网格DP)
			
题面 传送门:https://www.luogu.org/problemnew/show/P2051 Solution 看到这题,我们不妨先看一下数据范围 30pt:n,m<=6 显然搜索,直接 ...
 - 基于gin的golang web开发:访问mysql数据库
			
web开发基本都离不开访问数据库,在Gin中使用mysql数据库需要依赖mysql的驱动.直接使用驱动提供的API就要写很多样板代码.你可以找到很多扩展包这里介绍的是jmoiron/sqlx.另外还有 ...
 - centos 6.5 时间网络同步
			
安装 ntpdate sudo yum -y install ntp ntpdate 修改为上海时区 sudo vim /etc/sysconfig/clock ZONE = "Asia/S ...
 - Java Spring Cloud服务间调用
			
A服务是用户服务,B服务某个需求需要用户信息,而B服务无法连接用户的数据库(分库),需要让A服务查询用户信息. 在B服务写一个接口去调用A服务的某个请求 /** * 访问A服务 */ @FeignCl ...
 - c++11-17 模板核心知识(一)—— 函数模板
			
1.1 定义函数模板 1.2 使用函数模板 1.3 两阶段翻译 Two-Phase Translation 1.3.1 模板的编译和链接问题 1.4 多模板参数 1.4.1 引入额外模板参数作为返回值 ...
 - TCP粘包问题的解决方案02——利用readline函数解决粘包问题
			
主要内容: 1.read,write 与 recv,send函数. recv函数只能用于套接口IO ssize_t recv(int sockfd,void * buff,size_t len,i ...
 - binary hacks读数笔记(dlopen、dlsym、dlerror、dlclose)
			
1.dlopen是一个强大的库函数.该函数将打开一个动态库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.比如 Apache Web 服务器利用这个函数在运行过程中加载 ...