【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 ...
随机推荐
- Spring 最常用的 7 大类注解,哪些你还不知道?
随着技术的更新迭代,Java5.0开始支持注解.而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架. 而spring的的注解那 ...
- Docker composer搭建Spring Cloud Alibaba 运行环境(二)
" Spring Cloud Alibaba要用到的组件很多,注册中心nacos, 限流sentinel, 数据库,网关等等.由于用到的组件相对较多,部署会很繁琐,最关键的是没有资源服务器, ...
- Gym102012A Rikka with Minimum Spanning Trees
题意 \(T\) 组数据,每组数据给定一个 \(n\) 个点,\(m\) 条边,可能含有重边自环的图,求出最小生成树的个数与边权和的乘积,对 \(10^9+7\) 取模. \(\texttt{Data ...
- Luogu P4546 [THUWC2017]在美妙的数学王国中畅游
题意 题意奇奇怪怪,这里就不写了. \(\texttt{Data Range:}1\leq n\leq 10^5,1\leq m\leq 2\times 10^5\) 题解 为什么你们都是卡在数学方面 ...
- Java学习的第十六天
1. 向上转型 向下转型 静态绑定 2.无问题 3.明天学习static关键字和final关键字
- 记录电子竞技游戏jesp中的传输过程公式
1.json数据转换成字典 dict1 = json.load(load_f1) dict2 = json.load(load_f2) 2.将两个字典按key排好序,然后使用zip()函数将两个字典对 ...
- 自动化测试之Selenium篇(一):环境搭建
当前无论找工作或者是实际项目应用,自动化测试扮演着非常重要的角色,今天我们来学习下Selenium的环境搭建 Selenium简述 Selenium是一个强大的开源Web功能测试工具系列 可进行读入测 ...
- SAM学习笔记&AC自动机复习
形势所迫,一个对字符串深恶痛绝的鸽子又来更新了. SAM 后缀自动机就是一个对于字符串所有后缀所建立起的自动机.一些优良的性质可以使其完成很多字符串的问题. 其核心主要在于每个节点的状态和$endpo ...
- .NetCore HttpClient发送请求的时候为什么自动带上了一个RequestId头部?
奇怪的问题 最近在公司有个系统需要调用第三方的一个webservice.本来调用一个下很简单的事情,使用HttpClient构造一个SOAP请求发送出去拿到XML解析就是了. 可奇怪的是我们的请求在运 ...
- Python基础教程分享,视频教程免费下载!
给大家分享一套我初学Python时看的一套基础教程,是视频教程,免费分享给大家,希望对正在学习Python或者打算学习Python的朋友有帮助哈~~ 废话不多说 为期92天的Python基础教程视频教 ...