题意:
就是求A的B次方摸9901;
主要是数据太大,五千万的五千万。。。
理解:
开始做的时候看到确实没想法;
然后去做其他题了,之后他们都过了;
我就问了他们,他们说因子分解;
于是我就再推了哈;
发现可以做;
怎么做呢?
先对A质因子分解;
然后推出:
(1 + q^1 + q^2 +......+ q^B) *(1 + p^1 + p^2 +......+ p^B)*......
这个公式可以看出就是几个等比数列相乘;
然后拿出等比数列公式:
Sn = (1 - q^(n + 1)) / (1 - q) ;
这个公式大家都会,就是不能直接算,因为有除法,不能取模;
之后再推,发现可以将下面那个(1 - q)约去;
于是就有以下公式:
n为偶数:
1 - q^n = (1 - q^(n/2)) * (1 + q^(n/2)) ;
n为奇数:
1 - q^n = (1 - q^ ( (n - 1) / 2) ) * ( 1 + q^ ( (n - 1) / 2 ) ) + q^(n - 1) *(1 - q) ;
根据这两个公式递归,就对了;
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define ll long long
#define P pair<int, int>
#define x first
#define y second
vector<bool> isprime(10000 + 10);
vector<ll> prime;
void init()
{
for (int i = 0; i < 10000 + 10; ++i)
{
isprime[i] = true;
}
for (ll i = 2; i * i <= 50000000; ++i)
{
if (isprime[i])
{
prime.push_back(i);
for (ll j = 2 * i; j * j <= 50000000; j += i)
{
isprime[j] = false;
}
}
}
}
ll poww(ll a, ll b)
{
ll sum = 1;
while (b != 0)
{
if (b % 2 == 1)
{
sum = (sum * a) % 9901;
}
a = (a * a) % 9901;
b /= 2;
}
return sum;
}
ll search(ll q, ll n)
{
ll sum = 1;
if (n == 1) return sum;
if (n == 2) return sum = (sum * (1 + q)) % 9901;
if (n % 2 == 1)
{
sum = (((search(q, (n - 1) / 2) * (1 + poww(q, (n - 1) / 2))) % 9901) + poww(q, n - 1)) % 9901;
}
else
{
sum = (search(q, n / 2) * (1 + poww(q, n / 2))) % 9901;
}
return sum;
}
int main()
{
init();
ll A, B;
scanf("%lld%lld", &A, &B);
ll ans = 1;
for (int i = 0; i < prime.size(); ++i)
{
if (A == 1) break;
if (A % prime[i] != 0) continue;
ll c = 0;
while (A % prime[i] == 0)
{
++c;
A /= prime[i];
}
ans = (ans * search(prime[i], B * c + 1)) % 9901; //这儿的B * c + 1 是因为等比数列的最大项就是这么多,可以推一推的;
}
if (A != 1)
{
ans = (ans * search(A, B + 1)) % 9901;
}
printf("%lld\n", ans);
return 0;
}