大致题意:

求A^B的所有约数(即因子)之和,并对其取模 9901再输出。

解题思路:

应用定理主要有三个:

(1)   整数的唯一分解定理:

任意正整数都有且只有一种方式写出其素因子的乘积表达式。

A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   其中pi均为素数

(2)   约数和公式:

对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)

有A的所有因子之和为

S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)

(3)   同余模公式:

(a+b)%m=(a%m+b%m)%m

(a*b)%m=(a%m*b%m)%m

有了上面的数学基础,那么本题解法就很简单了:

1: 对A进行素因子分解

分解A的方法:

A首先对第一个素数2不断取模,A%2==0时 ,记录2出现的次数+1,A/=2;

当A%2!=0时,则A对下一个连续素数3不断取模...

以此类推,直到A==1为止。

注意特殊判定,当A本身就是素数时,无法分解,它自己就是其本身的素数分解式。

最后得到A = p1^k1 * p2^k2 * p3^k3 *...* pn^kn.
      故 A^B = p1^(k1*B) * p2^(k2*B) *...* pn^(kn*B);

2:A^B的所有约数之和为:

sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...* [1+pn+pn^2+...+pn^(an*B)].

3: 用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n:

(1)若n为奇数,一共有偶数项,则:
      1 + p + p^2 + p^3 +...+ p^n

= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
      = (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))

上式加粗的前半部分恰好就是原式的一半,那么只需要不断递归二分求和就可以了,后半部分为幂次式,将在下面第4点讲述计算方法。

(2)若n为偶数,一共有奇数项,则:
      1 + p + p^2 + p^3 +...+ p^n

= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
      = (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);

上式加粗的前半部分恰好就是原式的一半,依然递归求解

4:反复平方法计算幂次式p^n

这是本题关键所在,求n次幂方法的好坏,决定了本题是否TLE。

以p=2,n=8为例

常规是通过连乘法求幂,即2^8=2*2*2*2*2*2*2*2

这样做的要做8次乘法

而反复平方法则不同,

定义幂sq=1,再检查n是否大于0,

While,循环过程若发现n为奇数,则把此时的p值乘到sq

{

n=8>0 ,把p自乘一次, p=p*p=4     ,n取半 n=4

n=4>0 ,再把p自乘一次, p=p*p=16   ,n取半 n=2

n=2>0 ,再把p自乘一次, p=p*p=256  ,n取半 n=1,sq=sq*p

n=1>0 ,再把p自乘一次, p=p*p=256^2  ,n取半 n=0,弹出循环

}

则sq=256就是所求,显然反复平方法只做了3次乘法

//Memory Time
//336K 0MS #include<iostream>
using namespace std; const int size=;
const int mod=; __int64 sum(__int64 p,__int64 n); //递归二分求 (1 + p + p^2 + p^3 +...+ p^n)%mod
__int64 power(__int64 p,__int64 n); //反复平方法求 (p^n)%mod int main(void)
{
int A,B;
int p[size];//A的分解式,p[i]^n[i]
int n[size]; while(cin>>A>>B)
{
int i,k=; //p,n指针 /*常规做法:分解整数A (A为非质数)*/
for(i=;i*i<=A;) //根号法+递归法
{
if(A%i==)
{
p[k]=i;
n[k]=;
while(!(A%i))
{
n[k]++;
A/=i;
}
k++;
}
if(i==) //奇偶法
i++;
else
i+=;
}
/*特殊判定:分解整数A (A为质数)*/
if(A!=)
{
p[k]=A;
n[k++]=;
} int ans=; //约数和
for(i=;i<k;i++)
ans=(ans*(sum(p[i],n[i]*B)%mod))%mod; //n[i]*B可能会超过int,因此用__int64 cout<<ans<<endl;
}
return ;
} __int64 sum(__int64 p,__int64 n) //递归二分求 (1 + p + p^2 + p^3 +...+ p^n)%mod
{ //奇数二分式 (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
if(n==) //偶数二分式 (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2)
return ;
if(n%) //n为奇数,
return (sum(p,n/)*(+power(p,n/+)))%mod;
else //n为偶数
return (sum(p,n/-)*(+power(p,n/+))+power(p,n/))%mod;
} __int64 power(__int64 p,__int64 n) //反复平方法求(p^n)%mod
{
__int64 sq=;
while(n>)
{
if(n%)
sq=(sq*p)%mod;
n/=;
p=p*p%mod;
}
return sq;
}

转载自:優YoU http://blog.csdn.net/lyy289065406/article/details/6648539

 

POJ1845 数论 二分快速取余的更多相关文章

  1. 洛谷 P1226 【模板】快速幂||取余运算

    题目链接 https://www.luogu.org/problemnew/show/P1226 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 ...

  2. 洛谷P1226 【模板】快速幂||取余运算

    题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整数b,p,k. 输出格式: 输出“b^p mod k=s” s为运算结果 S1: ...

  3. LuoguP1226 【模板】快速幂||取余运算

    题目链接:https://www.luogu.org/problemnew/show/P1226 第一次学快速幂,将别人对快速幂原理的解释简要概括一下: 计算a^b时,直接乘的话计算次数为b,而快速幂 ...

  4. hdu1061Rightmost Digit(快速幂取余)

    Rightmost Digit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  5. Codeforces Round #534 (Div. 2) D. Game with modulo(取余性质+二分)

    D. Game with modulo 题目链接:https://codeforces.com/contest/1104/problem/D 题意: 这题是一个交互题,首先一开始会有一个数a,你最终的 ...

  6. 洛谷——P1226 取余运算||快速幂

    P1226 取余运算||快速幂 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整数b,p,k. 输出格式: 输出“b^p mod ...

  7. 洛谷 P1226 取余运算||快速幂

    P1226 取余运算||快速幂 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整数b,p,k. 输出格式: 输出“b^p mod ...

  8. LightOJ - 1282 - Leading and Trailing(数学技巧,快速幂取余)

    链接: https://vjudge.net/problem/LightOJ-1282 题意: You are given two integers: n and k, your task is to ...

  9. Uint47 calculator【map数组+快速积+各种取余公式】

    Uint47 calculator 题目链接(点击) In the distant space, there is a technologically advanced planet. One day ...

随机推荐

  1. ubuntu dash

    缘由:写一些脚本放在/etc/rc.loca自动执行开机启动报错 fiail to start /etc/rc.local 查找资料 缘起:ubuntu在6.0后默认bash改为了dash  导致很多 ...

  2. .NET基本权限管理框架源代码

    有兴趣的朋友欢迎加群讨论:312677516 1.菜单导航管理 2.操作按钮 3.角色管理 4.部门管理 5.用户管理(用户权限) 6.用户组管理(设置成员,用户组权限) 7.系统配置(动态配置系统参 ...

  3. 数据持久化之CoreData

    再次回归博客园, 已经实属不易了, 面临这近期忙忙碌碌的项目开发, 虽然并不是完全的没有闲暇时间, 但是怎么说呢, 也有着各种的无奈与曲折, 面临这产品需求的不断变化和页面的不断更新, 对于一个程序员 ...

  4. jQuery中DOM操作

    1 定义:jquery中对DOM的操作就是对DOM元素进行增删查改操作 2 分类:      1)DOM Core(核心):用途广泛 支持多种编程语言 2)HTML DOM:代码简短 只用于处理web ...

  5. SQLServer2008/2012 删除所有表视图存储过程

    SQLServer2008/2012 删除所有表视图存储过程 -------------------删除所有的表-------------------use xuwenbin111--/第1步**** ...

  6. java 位运算权限管控(转载)

    这里笔者介绍一种很常用,也比较专业的权限控制思路.这里用java语言描述,其实都差不多的.要换成其他的语言主,自己转一下就可以了.为了方便起见,我们这里定义a^b为:a的b次方.这里,我们为每一个操作 ...

  7. AngularJs练习Demo18 Resource

    @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport&quo ...

  8. mysql 分区表详解

    项目中要一张库表实现 list分区.并且支持多种数据库. oracle 很顺利,只是mysql 听说5.1版本就已经支持了, 可是试了很多个版本,都不行,后来查到原因是要5.5 以上版本 分区才支持 ...

  9. 高放的c++学习笔记之lambda表达式

    lambda表达式:可以让代码看起来更整洁,有些结构简单且用的次数少的函数可以用lambda表达式替代, 通常结构是这样的[捕获列表](参数列表){函数部分} 捕获列表: lambda表达式如果在一个 ...

  10. POJ3104 Drying(二分查找)

    POJ3104 Drying 这个题由于题目数据比较大(1 ≤ ai ≤ 109),采用贪心的话肯定会超时,自然就会想到用二分. 设C(x)为true时表示所用时间为X时,可以把所有的衣服都烘干或者自 ...