约数之和(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 秒 ...
随机推荐
- Flex带Checkbox的Tree
想把Flex自带的Tree控件改成带有checkbox的样式. 原本以为同DataGrid一样,添加一个ItemRenderer就行,结果发现行不通. 进Tree控件的源码看了一下,发现Tree在自己 ...
- kali linux 2019.4设置为中文方法
就在前天,2019年11月26日,kali Linux官网发布了最新版本:Kali Linux 2019.4发行版,此版本和之前相比变动很大,系统界面.主题.壁纸都灿然一新. Kali Linux20 ...
- linux 内核版本和发行版本区别
内核版本:我的理解是,内核是系统的心脏,是linux中最基层的代码.版本号如 Linux version 3.10.0-514.el7.x86_64 查看内核版本可使用.uname -a 或者cat ...
- Java包package之间调用问题-cmd运行窗口编译运行
问题:在使用了java包机制(package)后,编译出现错误:找不到或无法加载主类 xxx 的错误提示信息(各种编译不通过) 先给演示结果: 编译:javac -d classes src/a/He ...
- kubernetes实战(二十九):Kubernetes RBAC实现不同用户在不同Namespace的不同权限
1.基本说明 在生产环境使用k8s以后,大部分应用都实现了高可用,不仅降低了维护成本,也简化了很多应用的部署成本,但是同时也带来了诸多问题.比如开发可能需要查看自己的应用状态.连接信息.日志.执行命令 ...
- C# partial 关键字分析
简单的来说 partial是局部类型的意思 就是说有这个关键字的类.结构或接口可以写成几个部分 比如 public partial class Program { static void Main(s ...
- node.js多进程架构
node.js是单进程应用,要充分利用多核cpu的性能,就需要用到多进程架构. 作为web服务器,不能多个进程创建不同的socket文件描述符去accept网络请求, 有经验的同学知道,如果端口被占用 ...
- 链表-C语言实现
链式存储线性表的结构体: typedef int ElemType; //元素类型 typedef struct Node //链表结构体 { ElemType date; //链表结点数据域 str ...
- 《Windows内核安全与驱动开发》阅读笔记 -- 索引目录
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 一.内核上机指导 二.内核编程环境及其特殊性 2.1 内核编程的环境 2.2 数据类型 2.3 重要的数据结构 2.4 函数调 ...
- golang数据结构之循环链表
循环链表还是挺有难度的: 向链表中插入第一条数据的时候如何进行初始化. 删除循环链表中的数据时要考虑多种情况. 详情在代码中一一说明. 目录结构如下: circleLink.go package li ...