题意: 求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. throw和throws

    uncheckException的处理 class User{ private int age; public void setAge(int age){ if(age < 0){ //生成异常 ...

  2. Mysql账号管理

    一 用户添加 通过insert 方式添加用户 insert into mysql.user(Host,User,Password) values("localhost"," ...

  3. CentOS 7 + nginx + uwsgi + web2py (502 bad gateway nginx)

    Web2py开发包中自带的setup-web2py-nginx-uwsgi-centos64.sh脚本, 只能运行在CentOS 6.4中使用, 如果直接在CentOS 7 中使用该脚本布署后, 访问 ...

  4. golang实现ping命令

    // Copyright 2009 The Go Authors.  All rights reserved.// Use of this source code is governed by a B ...

  5. Python实现Apriori

    Python实现Apriori 运行环境 Pyhton3 计算过程 st=>start: 开始 e=>end: 结束 op1=>operation: 读入数据 op2=>ope ...

  6. homework-07 C++ 11 能好怎

    大二时候学过c++,但是那只是为了考试在学习,大作业也就写了一个读写者线程同步的模拟,连一个完整的类都没有写过,所以我必须承认对c++了解的很少. 对于C++ 11这一新标准,我首先阅读了来自前C++ ...

  7. [rsync+inotify]——监控客户端文件变化,rsync同步到服务器

    关于rsync的配置请参考博文:http://www.cnblogs.com/snsdzjlz320/p/5630695.html 实验环境 (1) Rsync服务器:10.0.10.158 (2) ...

  8. 如何设置potplayer播放时总在最前端

    1.测试平台:potplayer 64位 2.步骤:在播放器界面上点击右键->选项->基本->最前端方式-选播放视频时在最前端(或是总在最前端) 3.选择:基本->最前端方式- ...

  9. 用C语言实现的扑克牌洗牌程序

    一副牌:54张 从0开始排序: 0-12表示黑桃   A 1,2,3,... 10,J,Q,K 13-25表示红桃 A 1,2,3,... 10,J,Q,K 26-38表示草花 A 1,2,3,... ...

  10. [转载]ubuntu下如何更改mysql数据存放路径

    http://www.gaojinbo.com/ubuntu%E4%B8%8B%E5%A6%82%E4%BD%95%E6%9B%B4%E6%94%B9mysql%E6%95%B0%E6%8D%AE%E ...