题意: 求A^B的所有正因子的和,最后模9901的结果。

思路:

若对一个数n进行素数分解,n=p1^a1*p2^a2*p3^a3*...*pk^ak
那么n的所有正因子之和sum=(1+p1+...+p1^a1)*(1+p2+...+p2^a2)*...*(1+pk+...+pk^ak)
然后可以用等比数列求和公式(pk^(ak+1)-1)/(pk-1)求每项的和,再累乘。
用等比数列求1+pk+...+pk^ak时候要注意几点:

1.这里有除法,所以模的时候要将除以分母转化成乘以分母的逆元
a = (b/c) ==> a%m = b*c^(m-2)%m ( m为素数 )
证明:
b = a * c
根据费马小定理 a^(p-1)= 1 %p;(p是素数且a不能整除p)
所以 c^(m-1)%m=1%m
因此 a % m = a*1%m = a * c^(m-1)%m = a*c*c^(m-2)%m = b*c^(m-2)%m;

2.等比求和公式要注意,分母pk-1不能为0。
当pk%mod=1的时候, (1+pk+...+pk^ak)%mod=ak+1

3.当pk%mod=0的时候,(1+pk+...+pk^ak)=1,可以直接pass即可

还有从discuss里看到别人求和的做法:
1.可以首先计算rem=p^(cB+1)%(MOD*(p-1))
2.然后计算rem=(rem-1+MOD*(p-1))/(p-1)
3.最后计算rem%MOD
这里MOD*(p-1)可能会超过32位,所以在计算p^(cB+1)%(MOD*(p-1))时候可能乘法会溢出....careful....
证明:
令t*(p-1)=(p^0+p^1+p^2+...+p^a)*(p-1)=p^(a+1)-1 (mod m*(p-1))
因为gcd(p-1,m*(p-1))=p-1且 (p-1)|p^(a+1)-1 ,所以t=(p^(a+1)-1)/(p-1) (mod m)
因此我们可以先求p^(a+1)-1 (mod m*(p-1)),再把这个值除以(p-1)后取mod m

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h> using namespace std;
long long A,B;
const int mod=;
const int maxn=;
bool isprime[maxn];
int prime[maxn];
int cnt=; void init(){
memset(isprime,true,sizeof(isprime));
for(int i=;i<maxn;i++){
if(isprime[i]){
prime[cnt++]=i;
for(int j=*i;j<maxn;j+=i)
isprime[j]=false;
}
}
}
long long quickPow(long long a,long long b){
long long ret=;
while(b){
if(b&)
ret=ret*a%mod;
a=a*a%mod;
b=b>>;
}
return ret;
}
long long solve(long long a,long long b){
int c;
long long ans=;
for(int i=;i<cnt;i++){
c=;
if(a%prime[i]==){
while(a%prime[i]==){
c++;
a=a/prime[i];
}
if(prime[i]%mod==)
continue;
else if(prime[i]%mod==){
//(1+p+p^2+...+p^cb),此时求和不能用等比,因为分母(p-1)!=0。模9901后的和为c+1
ans=(ans*(c*b+))%mod; //注意:是c*b+1,一开始写成了c+1。
}
else{
long long ret=(quickPow((long long)prime[i],(long long)(c*b+))-+mod)%mod;
ans=(ans*(ret*quickPow((long long)(prime[i]-),(long long)(mod-))%mod))%mod;
}
}
}
//不要忘记了最后的a若大于1,则为素因子
if(a>){
if(a%mod==)
return ans;
else if(a%mod==){
ans=(ans*(b+))%mod; //注意:由于这里c=1,所以是b+1,一开始写成了2,也忘记乘以b了。
}
else{
long long ret=(quickPow(a,(long long)(b+))-+mod)%mod;
ans=(ans*(ret*quickPow(a-,(long long)(mod-))%mod))%mod;
}
}
return ans;
}
int main()
{
init();
while(scanf("%I64d%I64d",&A,&B)!=EOF){
printf("%I64d\n",solve(A,B));
}
return ;
}

也可以用二分来求 1+p+...+p^m

1.当m=2*k时:
p+...+p^2k=(1+p^k)(p+p^2+...+p^k)
2.当m=2*k+1时:
p+...+p^2k+p^(2k+1)=(1+p^k)(p+p^2+...+p^k)+p^(2k+1)

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm> using namespace std; const int maxn=;
int cnt,prilen;
long long A,B;
int shu[]; //存储质因数
int num[]; //存储相应的质因数个数 /**
用于处理n的质因数
*/
void eular(int n) {
memset(num,,sizeof(num));
int i;
cnt=;
for (i=; i*i<=n; i++) {
if (n%i==) {
cnt++;
n/=i;
shu[cnt]=i;
num[cnt]++;
while (n%i==) {
n/=i;
num[cnt]++;
}
}
}
if(n>){
cnt++;
shu[cnt]=n;
num[cnt]++;
}
}
//这里传入参数的a和b值要定义为long long,否则答案不对
long long quickPow(long long a,long long b) {
long long ans=;
while(b>) {
if(b&) {
ans=(ans*a)%;
}
a=(a*a)%;
b=b>>;
}
return ans;
}
/**
计算p+...+p^n;
*/
long long cal(long long p,long long n){
long long ans=;
if(n==)
return ;
if(n&){
ans=((cal(p,n-)%)+(quickPow(p,n)%))%;
}
else{
ans=(((+quickPow(p,n/))%)*(cal(p,n/)%))%;
}
return ans%;
} long long sum(){
long long ans=;
for(int i=;i<=cnt;i++){
ans=(ans*(+cal(shu[i],num[i]*B))%)%;
}
return ans%;
} int main() {
scanf("%lld%lld",&A,&B);
eular(A);
printf("%I64d\n",sum());
return ;
}

 

POJ 1845 Sumdiv (求某个数的所有正因子的和)的更多相关文章

  1. poj 1845 POJ 1845 Sumdiv 数学模板

    筛选法+求一个整数的分解+快速模幂运算+递归求计算1+p+p^2+````+p^nPOJ 1845 Sumdiv求A^B的所有约数之和%9901 */#include<stdio.h>#i ...

  2. 算法笔记(c++)--求一个数的所有质数因子

    算法笔记(c++)--求一个数的所有质数因子 先贴题目: 这题不难,恶心在理解上面.最后看评论知道了怎么回事: 2*2*3*3*5=180 按照这逻辑的话应该输入的数由一系列质数相乘出来,所以每次找到 ...

  3. poj 1845 Sumdiv (等比求和+逆元)

    题目链接:http://poj.org/problem?id=1845 题目大意:给出两个自然数a,b,求a^b的所有自然数因子的和模上9901 (0 <= a,b <= 50000000 ...

  4. POJ 1845 Sumdiv(求因数和 + 逆元)题解

    题意:给你a,b,要求给出a^b的因子和取模9901的结果. 思路:求因子和的方法:任意A = p1^a1 * p2^a2 ....pn^an,则因子和为sum =(1 + p1 + p1^2 + . ...

  5. poj 1845 Sumdiv 约数和定理

    Sumdiv 题目连接: http://poj.org/problem?id=1845 Description Consider two natural numbers A and B. Let S ...

  6. POJ 1845 Sumdiv 【二分 || 逆元】

    任意门:http://poj.org/problem?id=1845. Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions ...

  7. POJ 1845 Sumdiv(逆元)

    题目链接:Sumdiv 题意:给定两个自然数A,B,定义S为A^B所有的自然因子的和,求出S mod 9901的值. 题解:了解下以下知识点   1.整数的唯一分解定理 任意正整数都有且只有唯一的方式 ...

  8. POJ 1845 Sumdiv [素数分解 快速幂取模 二分求和等比数列]

    传送门:http://poj.org/problem?id=1845 大致题意: 求A^B的所有约数(即因子)之和,并对其取模 9901再输出. 解题基础: 1) 整数的唯一分解定理: 任意正整数都有 ...

  9. POJ 1845 Sumdiv#质因数分解+二分

    题目链接:http://poj.org/problem?id=1845 关于质因数分解,模板见:http://www.cnblogs.com/atmacmer/p/5285810.html 二分法思想 ...

随机推荐

  1. sqlserver中查找长时间未提交事务

    无论是有意无意,如果事务在数据库中保持打开,则它会阻塞其他进程对修改后的数据进行操作.同样,对事务日志进行备份也只会截断不活动事务的那部分事务日志,所以打开的事务会导致日志变多(甚至达到物理限制),直 ...

  2. linux kernel 0.11 head

    head的作用 注意:bootsect和setup汇编采用intel的汇编风格,而在head中,此时已经进入32位保护模式,汇编的采用的AT&T的汇编语言,编译器当然也就变成对应的编译和连接器 ...

  3. 分布式缓存Memcached

       分布式缓存服务器,既然用到数据缓存很明显就是想高效性的获取数据,大容量的存储数据.为了可以缓存大量的数据以及可以高效获取数据,那么分布式缓存数据库就要解决数据可以水平线性扩展,这样可以扩大数据容 ...

  4. chkconfig 命令详解

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法: chkconfig [--a ...

  5. core java 8~9(GUI & AWT事件处理机制)

    MODULE 8 GUIs--------------------------------GUI中的包: java.awt.*; javax.swing.*; java.awt.event.*; 要求 ...

  6. iOS进阶学习-CoreData

    一.CoreData数据库框架的优势 1.CoreData数据持久化框架是Cocoa API的一部分,首次在iOS5版本的系统中出现,它允许按照实体-属性-值模型组织数据,并以XML.二进制文件或者S ...

  7. iPhone的震动 基于SDK8.0 Swift实现

    导入AudioToolbox.framework包 在swift文件中  import AudioToolbox AudioServicesPlaySystemSound(SystemSoundID. ...

  8. ExtJS4.x 开发环境搭建

    需要的资源 ExtJS4.2 eclipse 开发环境搭建 在项目中国需要引用的文件: eclipse中有报错.需要处理的是ext-lang-zh_CN.js,中文编码不能识别.右键->属性-& ...

  9. mif_maker2010.exe下载和使用说明

    mif_malker2010.exe下载地址:http://pan.baidu.com/s/1bCqAp4 使用说明:http://www.cnblogs.com/BitArt/archive/201 ...

  10. ArcGIS Server10.2服务启动不了之http://localhost:6080/arcgis/manager无法打开之arcMap 无法打开6080admin问题解决之路

    遇到的问题:在services.msc中可以正常启动arcGIS server ,但是过几秒种服务就自动关闭, 而且manager打不开, 各种方法都试过了,什么关闭杀毒软件,更改服务配置文件,更改a ...