小M的因子和
时间限制:1000 ms | 内存限制:65535 KB
-
描述
-
小M在上课时有些得意忘形,老师想出道题目难住他。小M听说是求因子和,还是非常得意,但是看完题目是求A的B次方的因子和,有些手足无措了,你能解决这个问题吗?
-
输入
-
有多组测试样例
每行两个数 A ,B ,(1≤A,B≤10^9)
输出
- 输出A的B次方的因子和,并对9901取余。 样例输入
-
2 3
样例输出
15
-
有多组测试样例
算法引入:
为什么会有此个算法成立呢?在这里给出一个例子作为解释,如:
10 = 2^1 + 5^1,其因子和为(2^0 + 2^1)*(5^0 + 5^1)=(2^0*5^0) + (2^0*5^1) + (2^1*5^0) + (2^1*5^1) = 1 + 5 + 2 + 10;
题目解析:
过与简单就此省略。
思路解析:
我们知道没一个数都可以分解成由素数因子组成的数。so...你想到了没有。反正一开始我是没想到。就是把一个数分解成由有多个素数组成,且数可能有多个相同的素数组成。例如:8 = 2*2*2 = 2^3;10 = 2^1*5^1;so...现在你明白了没有,没有就算了。看来孩子你不适合数论。转行吧!!
所以经过上面的分析你懂的做了没有。还有就是,这题的N有点大,所以要用到分治思想和二分冪。
别的没什么好讲的,讲一下这题的分治思想吧。
a + a^2 + a^3 +.......+a^(n/2)+a^(n/2+1) + ......+ a^n = (a + a^2 + ......+a^(n/2)) + a^(n/2)*(a + a^2 + ....+a^(n/2))
= (a + a^2 +.....+ a^(n/2))*(1 + a^(n/2)) (n为奇数的时候,n为偶数的时候将会不同。自己思考为什么,或者看下面代码)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int MOD = 9901;
LL PowMod(LL base,LL n)
{
LL res = 1;
base %= MOD;
while(n)
{
if(n&1)
res = res*base%MOD;
base = base*base%MOD;
n >>= 1;
}
return res;
}
LL Sum(int base,int n)
{
if(n == 0)
return 1;
if(n&1) //odd
return(Sum(base,n/2)*(1+PowMod(base,n/2+1)))%MOD;
else
return(Sum(base,n/2-1)*(1+PowMod(base,n/2+1))+PowMod(base,n/2))%MOD;
}
int main()
{
int a,b;
while(~scanf("%d%d",&a,&b))
{
LL ans = 1;
int n = sqrt(a+0.5);
for(int i = 2;i <= n;++i)
{
if(a%i==0){ //·Ö½âÖÊÒò×Ó
int k = 0;
while(a%i==0)
{
a /= i;
++k;
}
ans = ans*Sum(i,k*b)%MOD;
}
}
if(a > 1){
ans = ans*Sum(a,b)%MOD;
}
printf("%d\n",int(ans));
}
return 0;
}
Geometric sum
-
描述
-
Compute (a + a^2 + … + a^n) mod m.
(a+a2+…an)mod
-
输入
-
Three integers a,n,m.
(1≤a,n,m≤10^18)
It ends with EOF.
输出
- The only integer denotes the result. 样例输入
-
2 2 1000000000
样例输出
-
6
-
Three integers a,n,m.
题意分析:
就是要你求 (a + a^2 + … + a^n)Mod m的值。可以看出n,m都是出奇的大,直接算肯定超时,只能想出一个O(N)的复杂度。
思路分析:
其实该题的考查的算法与上一题的是一样的,都是用到了分治思想。只是该题在处理的时候由于模太大了,所以要用到一个二进制的乘法取模的算法。既然是用到了新知识了,那就有必要介绍一下这个高级的东西。下面就给出二进制下的乘法取模模版吧
//base 为底数,n为次数,M为模
LL MulMode(LL base,LL n,LL M)
{
LL res = 0;
base %= M;
while(n)
{
if(n&1){
res += base;
if(res > m)
res -= m;
}
base <<= 1;
if(base > m)
base -= m;
n >>= 1;
}
return res;
}
然后该题的思路就与上面一题的思路就是相同的了,这里就不再赘述;
#include <stdio.h>
typedef long long LL;
LL m;
LL MulMod(LL base,LL n)
{
LL res = 0;
base %= m;
while(n)
{
if(n&1){
res += base;
if(res > m) res -= m;
}
base <<= 1;
if(base > m) base -= m;
n >>= 1;
}
return res;
}
LL PowMod(LL base,LL n)
{
LL res = 1;
base %= m;
while(n)
{
if(n&1)
res = MulMod(res,base);
base = MulMod(base,base);
n >>= 1;
}
return res;
}
LL Solve(LL a,LL n)
{
if(n == 1)
return a%m;
if(n&1)
return (Solve(a,n-1)+PowMod(a,n))%m;
LL tmp = Solve(a,n/2);
return MulMod(tmp,PowMod(a,n/2)+1);
}
int main()
{
LL a,n;
while(scanf("%lld%lld%lld",&a,&n,&m)!=EOF)
{
printf("%lld\n",Solve(a,n));
}
return 0;
}