约数之和(POJ1845 Sumdiv)
最近应老延的要求再刷《算法进阶指南》(不得不说这本书不错)...这道题花费了较长时间~(当然也因为我太弱了)所以就写个比较易懂的题解啦~
原题链接: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)
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)的更多相关文章
- 【题解】POJ1845 Sumdiv(乘法逆元+约数和)
POJ1845:http://poj.org/problem?id=1845 思路: AB可以表示成多个质数的幂相乘的形式:AB=(a1n1)*(a2n2)* ...*(amnm) 根据算数基本定理可 ...
- poj1845 Sumdiv
poj1845 Sumdiv 数学题 令人痛苦van分的数学题! 题意:求a^b的所有约数(包括1和它本身)之和%9901 这怎么做呀!!! 百度:约数和定理,会发现 p1^a1 * p2^a2 * ...
- POJ1845Sumdiv题解--约数之和
题目链接 https://cn.vjudge.net/problem/POJ-1845 分析 \(POJ\)里的数学题总是这么妙啊 首先有一个结论就是\(A=\prod{ \ {p_i}^{c_i} ...
- POJ1845 Sumdiv(求所有因数和+矩阵快速幂)
题目问$A^B$的所有因数和. 根据唯一分解定理将A进行因式分解可得:A = p1^a1 * p2^a2 * p3^a3 * pn^an.A^B=p1^(a1*B)*p2^(a2*B)*...*pn^ ...
- 51NOD 1220 约数之和 [杜教筛]
1220 约数之和 题意:求\(\sum_{i=1}^n \sum_{j=1}^n \sigma_1(ij)\) \[ \sigma_0(ij) = \sum_{x\mid i}\sum_{y\mi ...
- POJ1845 sumdiv 数论
正解:小学数学数论 解题报告: 传送门! 其实不难但我数学这个方面太菜了所以还是多写点儿博客趴QAQ 然后因为是英文的所以先翻译一下,,,? 大概就是说求AB的所有约数之和,对9901取膜 这个只需要 ...
- 【动态规划】mr359-最大公约数之和
[题目大意] 选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大. 输入一个正整数S. 输出最大的约数之和. 样例输入 Sample Input 11 样例输出 Sample ...
- POJ1845 Sumdiv 数学?逆元?
当初写过一篇分治的 题意:求A^B的所有因子之和,并对其取模 9901再输出 对于数A=p1^c1+p2^c2+...+pn*cn,它的所有约数之和为(1+p1+p1^2+p1^3+...+p1^(c ...
- 51Nod 约数之和
1220 约数之和 题目来源: Project Euler 基准时间限制:3 秒 ...
随机推荐
- ArcGIS 重新创建几何服务(GeometryService)
#参考官方网址:http://enterprise.arcgis.com/zh-cn/server/10.4/administer/windows/re-creating-the-geometry-s ...
- 洛谷P2634 聪聪可可 (点分治)
###题目链接### 题目大意: 给你一棵树,假如树上两点间的距离是 3 的倍数 的点对有 s 对,则输出最简分数 s/n ,其中 n 表示所有整棵树的点对总数. 分析: 1.显然,可以采用点分治. ...
- 如何使用C#调用C++类虚函数(即动态内存调用)
本文讲解如何使用C#调用只有.h头文件的c++类的虚函数(非实例函数,因为非虚函数不存在于虚函数表,无法通过类对象偏移计算地址,除非用export导出,而gcc默认是全部导出实例函数,这也是为什么 ...
- nginx离线部署脚本
#! /bin/bashbasepath=$(cd `dirname $0`; pwd)nginx_path=/usr/localfile_name=nginxecho "--------- ...
- nginx重启后,反向代理失败之问题排查记录
问题与排查过程 本地开发环境的服务器,部署了nginx,nginx上对静态的web前端页面进行了http 80端口代理:然后呢,因为一些原因,服务器重启了,重启服务器后,我去把nginx启动起来,但是 ...
- Django4模型(操作数据库)
模型入门同步数据库的两个指令创建模型注意事项1.外键ForeignKey 模型入门 同步数据库的两个指令 python manage.py makemigrations python manage.p ...
- MySQL双日志
InnoDB引擎的redo log日志 解决什么问题? 我们每次更新数据如果都要直接写到硬盘存储的话,如果更新数据频繁的话,整个过程的Io成本和查找成本都会很高(比方说每次启动磁盘,平均的寻找数据时间 ...
- 原创001 | 搭上SpringBoot自动注入源码分析专车
前言 如果这是你第二次看到师长的文章,说明你在觊觎我的美色!O(∩_∩)O哈哈~ 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 本系列为SpringBoot深度源码专车系列,第一篇发车 ...
- 全面认识 RUST -- 掌控未来的雷电
文章目录 RUST 简介 如何衡量语言的好坏? 静态语言 编译器 语言定位 代表性项目 Hello World RUST 前景 RUST 简介 Rust 是一种兼顾内存安全.高并发和稳定运行的编程语言 ...
- 数据库Oracle的安装与卸载
Oracle的安装步骤: 口令管理里面有scott,需要重新设置其口令,scott是测试表,里面有现成的表可以用来做实验. Oracle 自带客户端工具 SQLPlus sys 用户登录命令: sy ...