求一个等比数例之和, 并让他对一个数取模。
用到等比数列求和公式, 快速幂, 逆元。
不会证明, 下面给出代码。
#include <stdio.h>
#include <string.h>
#include <math.h>
typedef long long ll;
ll multi(ll a,ll b,ll m) // 二分乘法
{
ll ans = 0;
a %= m;
while(b)
{
if(b & 1)
{
ans = (ans + a) % m;
b--;
}
b >>= 1;
a = (a + a) % m;
}
return ans;
}
ll quick_mod(ll a,ll b,ll mod)
{
ll res = 1;
while(b)
{
if(b % 2 == 1)
res = multi(res, a, mod);
// 二分乘法 不然会数据溢出
b >>= 1;
a = multi(a, a, mod);
// 二分乘法 不然会数据溢出
}
return res;
}
int main()
{
ll a, b, mod=9901;
scanf("%I64d %I64d",&a, &b);
// 首项为 1 , 公比为 a,长度 为 b 的等比数例求和
printf("%I64d\n",((quick_mod(a,b,mod*(a-1)) - 1) / (a-1)));
return 0;
}
Sumdiv
Time Limit: 1000MS | | Memory Limit: 30000K |
Total Submissions: 23623 | | Accepted: 5876 |
Description
Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).
Input
The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.
Output
The only line of the output will contain S modulo 9901.
Sample Input
2 3
Sample Output
15
Hint
2^3 = 8.
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
思路: 举一个例子: 36, 1。
先把 36 分解成质因数, 2, 2,3, 3。
ans = 1 , 2, 2*2, 1*(3 + 3*3), 2 * (3 + 3*3) , 2*2 *(3 * 3). 之和。
#include <stdio.h>
#include <string.h>
#include <math.h>
typedef long long ll;
int p[10005];
void prime() // 打一个素数表
{
p[1] = 2;
int cnt = 1;
for(int i=3; i<=10000; i+=2)
{
int flag = true;
for(int j=2; j*j<=i; j++)
{
if(i%j == 0)
{
flag = false;
break;
}
}
if(flag)
p[++cnt] = i;
}
}
ll multi(ll a,ll b,ll m) // 二分乘法
{
ll ans = 0;
a %= m;
while(b)
{
if(b & 1)
{
ans = (ans + a) % m;
b--;
}
b >>= 1;
a = (a + a) % m;
}
return ans;
}
ll quick_mod(ll a,ll b,ll mod) // 快速幂
{
ll res = 1;
while(b)
{
if(b % 2 == 1)
res = multi(res, a, mod);
b >>= 1;
a = multi(a, a, mod);
}
return res;
}
int main()
{
ll a, b, mod=9901;
scanf("%I64d %I64d",&a, &b);
if(a == 1)
{
printf("1\n");
return 0;
}
prime();
ll ans = 1;
int num = 0;
for(int i=1; p[i]*p[i]<=a; i++)
{
if(a % p[i] == 0) // 寻找每个质因数 和 它的数量 num。
{
num=0;
while(a % p[i] == 0)
{
num++;
a /= p[i];
}
ll m =(p[i] - 1) * mod;
ans *= ((quick_mod(p[i], num*b+1, m) + m - 1) / (p[i]-1)); // 等比数列求和
// printf("%lld\n",(quick_mod(p[i], num*b+1, m) + m - 1) / (p[i]-1) % mod);
ans %= mod;
}
}
ll m = mod * (a - 1);
if(a > 1)
printf("%I64d\n",ans * ((quick_mod(a, b+1, m) + m - 1) / (a-1)) % mod);
else
printf("%I64d\n",ans % mod);
return 0;
}