最近应老延的要求再刷《算法进阶指南》(不得不说这本书不错)...这道题花费了较长时间~(当然也因为我太弱了)所以就写个比较易懂的题解啦~

原题链接:POJ1845

翻译版题目(其实是AcWing上的):

假设现在有两个自然数A和B,S是AB的所有约数之和。

请你求出S mod 9901的值是多少。

输入格式

在一行中输入用空格隔开的两个整数A和B。

输出格式

输出一个整数,代表S mod 9901的值。

数据范围

0≤A,B≤5×107

输入样例:

2 3

输出样例:

15

注意: A和B不会同时为0。

首先看到这题就知道不能打暴力(这还用你说),那就需要找一个巧方法

那么,什么是约数呢?

约数嘛,顾名思义,可以约掉的数,其实就是因数

如果你连因数都不知道就只好自行百度了

但其实百度还挺有用的

以下是约数的定义:

约数,又称因数整数a除以整数b(b≠0) 除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a。a称为b的倍数,b称为a的约数。在大学之前,"约数"一词所指的一般只限于正约数。约数和倍数都是二元关系的概念,不能孤立地说某个整数是约数或倍数。一个整数的约数是有限的。同时,它可以在特定情况下成为公约数。

但你再往下翻你会找到这个东西:

恩?这不就是质因数分解吗?

根据这个思路,我们很容易得到以下结论:

若A=P1c1*P2c2*...*Pncn ,那么AB就等于

P1B*c1*P2B*c2*...*PnB*cn 

又因为AB的约数集合可以看做其每一个质因数分别相乘得出的结果的集合

举个例子便于理解:

12=22*31

所以12的因数集合为

{1,2,3,2*2,2*3,2*2*3}={1,2,3,4,6,12}

可以看做把12的质因数分别组合相乘

那么我们把这个式子加起来可以得到

1+2+3+2*2+2*3+2*2*3

稍微改造一下

(1+2+2*2)(1+3)

似乎有点眉目了?

那么AB的约数之和由此可得:

(1+P1+P12+....+P1B*c1)*(1+P2+P22+....+P2B*c2)*....*(1+Pn+Pn2+....+PnB*cn)

(这段真他喵的难打)

根据同余定理,我们在求AB%9901就相当于以上每一个式子%9901再相乘

那么问题就又到了如何求(1+P+P2+....+Pc

因为同余对于除法没有分配率,所以这道题不能使用等比数列求和公式....

所以这时候我们想到了.....

分治!

将求解(1+P+P2+....+Pc)定义为sum(p,c),则有:

当c为奇数时:

sum(p,c)=(1+P+....+P(c-1)/2)+(1+P(c+1)/2+...+Pc

                     =(1+P+....+P(c-1)/2)+P(c+1)/2 *(1+P+....+P(c-1)/2
                     =(1+P(c+1)/2)*(1+P+....+P(c-1)/2
当c为偶数时,同理得:
sum(p,c)=(1+Pc/2)*(1+P+....+Pc/2-1)+Pc
(打这个更累!!!!)
这样,我们在每次求解时都可以将问题简化,配合快速幂就可以用θ(log n)的时间复杂度得到正确答案
.....
所以,你应该会分解质因数吧?
......
不会吗?
orz

由此可见,虽然我们知道了具体解法,但码出代码好像还有点问题....
但其实分解质因数是相当简单的!(而且时间复杂度只有θ(n)(大概吧))
相信大家都会判断一个数是否是质数~
那就是从2试到根号n,若有n可以整除的则n不是质数,若没有则n为质数
同理,我们可以从2开始试n的因子(试到根号n),然后除掉所有的因子并计数
(这种算法叫试除法)
以下代码:
    int m=;
for(int i=;i<=sqrt(n);i++)
{
if(n%i==)
m++,yz[m]=i;//yz数组存分解出的因子
while(n%i==)//除掉所有的i
{
n/=i;
gs[m]++;//gs数组存每个因子的个数
}
}
if(n>)
m++,yz[m]=n,gs[m]=;
for(int i=;i<=m;i++)
printf("%d^%d\n",yz[i],gs[i]);

还有一种更优的算法,叫做“Pollard's Rho”算法,但有点复杂(我懒得写),可以自行去查 已经帮你查好了←

那么这道题就可以写出来了~(我相信你会快速幂)

以下AC代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
const int N=;
int yz[],gs[];//分别用来存储质因子及其个数
int quick(int a,int b)//快速幂
{
long long t;
if(b==)return a%N;
if(b%==)
{
t=quick(a,b/);
return t%N*t%N;
}
else
{
t=quick(a,b/);
t=t%N*t%N;
t=t%N*a%N;
return t%N;
}
}
long long sum(int p,int c)
{
if(c==) return ;//边界
if(c==) return p+;//边界*2,可写可不写,开始没加1出了点问题
if(c%)
return (+quick(p,(c+)/))%N*sum(p,c/)%N;//奇数
else
return (+quick(p,c/))%N*sum(p,c/-)%N+quick(p,c);//偶数
}
long long czs(int n,int b)//分解质因数
{
if(n==) return ;//特殊情况直接返回
if(b==) return ;
int m=,ans=;
for(int i=;i<=sqrt(n);i++)
{
if(n%i==)
m++,yz[m]=i;
while(n%i==)
{
n/=i;
gs[m]++;
}
}
if(n>)
m++,yz[m]=n,gs[m]=;
for(int i=;i<=m;i++)
ans=(ans%N*sum(yz[i],gs[i]*b)%N)%N;
return ans%N;
}
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%lld",czs(a,b)%N);
return ;
}
//写这么多%N是因为数据溢出www
//那个数据在下方,可以试一试能不能过
//输入:50000000 50000000
//输出:5531

终于完了 赶紧刷B站学习去了

感谢观看~ヽ( ̄▽ ̄)ノ

约数之和(POJ1845 Sumdiv)的更多相关文章

  1. 【题解】POJ1845 Sumdiv(乘法逆元+约数和)

    POJ1845:http://poj.org/problem?id=1845 思路: AB可以表示成多个质数的幂相乘的形式:AB=(a1n1)*(a2n2)* ...*(amnm) 根据算数基本定理可 ...

  2. poj1845 Sumdiv

    poj1845 Sumdiv 数学题 令人痛苦van分的数学题! 题意:求a^b的所有约数(包括1和它本身)之和%9901 这怎么做呀!!! 百度:约数和定理,会发现 p1^a1 * p2^a2 * ...

  3. POJ1845Sumdiv题解--约数之和

    题目链接 https://cn.vjudge.net/problem/POJ-1845 分析 \(POJ\)里的数学题总是这么妙啊 首先有一个结论就是\(A=\prod{ \ {p_i}^{c_i} ...

  4. POJ1845 Sumdiv(求所有因数和+矩阵快速幂)

    题目问$A^B$的所有因数和. 根据唯一分解定理将A进行因式分解可得:A = p1^a1 * p2^a2 * p3^a3 * pn^an.A^B=p1^(a1*B)*p2^(a2*B)*...*pn^ ...

  5. 51NOD 1220 约数之和 [杜教筛]

    1220 约数之和 题意:求\(\sum_{i=1}^n \sum_{j=1}^n \sigma_1(ij)​\) \[ \sigma_0(ij) = \sum_{x\mid i}\sum_{y\mi ...

  6. POJ1845 sumdiv 数论

    正解:小学数学数论 解题报告: 传送门! 其实不难但我数学这个方面太菜了所以还是多写点儿博客趴QAQ 然后因为是英文的所以先翻译一下,,,? 大概就是说求AB的所有约数之和,对9901取膜 这个只需要 ...

  7. 【动态规划】mr359-最大公约数之和

    [题目大意] 选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大. 输入一个正整数S. 输出最大的约数之和. 样例输入 Sample Input 11 样例输出 Sample ...

  8. POJ1845 Sumdiv 数学?逆元?

    当初写过一篇分治的 题意:求A^B的所有因子之和,并对其取模 9901再输出 对于数A=p1^c1+p2^c2+...+pn*cn,它的所有约数之和为(1+p1+p1^2+p1^3+...+p1^(c ...

  9. 51Nod 约数之和

                              1220 约数之和                                  题目来源: Project Euler 基准时间限制:3 秒 ...

随机推荐

  1. web 开发常用字符串表达式匹配

    记录一下 web 开发中常用的一些字符串模式,这是我遇到的一些,后面如果还有的话,欢迎大神提出,会继续更新. 正则表达式 这个主要用在前端的验证,nginx 路径匹配,shell 脚本文本处理,后端感 ...

  2. 如何配置tomcat的环境变量

    如何配置tomcat的环境变量 安装好tomcat之后, 按照这个操作,计算机→属性→高级系统设置→高级→环境变量,打开环境变量设置框. 以本人的tomcat 8.0为例:安装下来如图 那么我的tom ...

  3. linuxLVM

    一.概念性的东西 LVM2:Logical Volume Manager ,Cersion 2 LVM,依赖于内核的dm模块(将一个或多个底层的设备组织成一个逻辑设备的模块).可以将多个物理分区通过软 ...

  4. Spring Cloud Alibaba(五)RocketMQ 异步通信实现

    本文探讨如何使用 RocketMQ Binder 完成 Spring Cloud 应用消息的订阅和发布. 介绍 RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的.高 ...

  5. 【Java基础】字面量相加的类型转换

    Java字面量的相加类型转换 1.Java 编译期间(javac),凡是字面量和常量的运算,都会先运算出结果 2.运行期当字符串池中有 String"字面量"时,Java 会直接用 ...

  6. No provider available for the service com.xxx.xxx 错误解决

    HTTP Status 500 - Servlet.init() for servlet springmvc threw exception type Exception report message ...

  7. scrapy请求传参-BOSS反爬

    scrapy请求传参-BOSS反爬 思路总结 首先boss加了反爬 是cookies的 爬取的内容为职位和职位描述 # -*- coding: utf-8 -*- import scrapy from ...

  8. Spring Cloud第三篇 | 搭建高可用Eureka注册中心

    ​ ​本文是Spring Cloud专栏的第三篇文章,了解前两篇文章内容有助于更好的理解后面文章: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring ...

  9. 搞IT产品,请谨记Mobile First

    我们在哪儿? 作为一名企业IT的老鸟,发现一个比较有意思的事情,就是我们的企业IT产品,仍然投入大量的精力,在基于PC的WEB端的设计和交付上,而在APP上的,移动端的考虑,一直都是在PC搞完之后,再 ...

  10. 手撕 JVM 垃圾收集日志

    下图是本篇的写作大纲,将从以下四个方面介绍怎么样处理 JVM 日志. 有准备才能不慌 想要分析日志,首先你得有日志呀,对不对.凡是未雨绸蒙总是没错的.所谓有日志的意思,你要把 JVM 参数配置好,日志 ...