原题链接:点击打开链接
题意:给定两个正整数和,求的所有因子和对9901取余后的值。
分析:先把分解得到,则得到,那么
的所有因子和的表达式如下
所以我们有两种做法。第一种做法是二分求等比数列之和。
代码:/*************************************************************************
> File Name: 1845.cpp
> Author: Clannad
> Mail: 821199012@qq.com
> Created Time: Mon 13 July 2016 08:55:16 PM
************************************************************************/
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include<string>
#include <ctime>
using namespace std;
typedef long long ll;
const int N = 10005;
const int MOD = 9901;
bool is_prime[N];
int prime[N];
void sieve(){
int p=0;
memset(is_prime,true,sizeof(is_prime));
is_prime[0]=is_prime[1]=false;
for(int i=2 ; i<N ; i++){
if(is_prime[i]){
prime[p++]=i;
for(int j=2*i ; j<N ; j+=i)is_prime[j]=false;
}
}
}
ll power(ll a,ll b)
{
ll ans = 1;
a %= MOD;
while(b)
{
if(b & 1)
{
ans = ans * a % MOD;
b--;
}
b >>= 1;
a = a * a % MOD;
}
return ans;
}
ll sum(ll a,ll n)
{
if(n == 0) return 1;
ll t = sum(a,(n-1)/2);
if(n & 1)
{
ll cur = power(a,(n+1)/2);
t = (t + t % MOD * cur % MOD) % MOD;
}
else
{
ll cur = power(a,(n+1)/2);
t = (t + t % MOD * cur % MOD) % MOD;
t = (t + power(a,n)) % MOD;
}
return t;
}
void solve(ll A,ll B){
ll ans=1;
for(int i=0 ; prime[i]*prime[i]<=A ; i++){
if(A%prime[i]==0){
int num=0;
while(A%prime[i]==0&&(A/=prime[i]))
num++;
ans*=sum(prime[i],num*B)%MOD;
ans%=MOD;
}
}
if(A>1){
ans*=sum(A,B)%MOD;
ans%=MOD;
}
cout<<ans<<endl;
}
int main()
{
ll A,B;
sieve();
while(cin>>A>>B){
solve(A,B);
}
return 0;
}
第二种方法就是用等比数列求和公式,但是要用逆元。用如下公式即可
因为可能会很大,超过int范围,所以在快速幂时要二分乘法。
代码:
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include<string>
#include <ctime>
using namespace std;
typedef long long ll;
const int N = 10005;
const int MOD = 9901;
bool is_prime[N];
int prime[N];
void sieve(){
int p=0;
memset(is_prime,true,sizeof(is_prime));
is_prime[0]=is_prime[1]=false;
for(int i=2 ; i<N ; i++){
if(is_prime[i]){
prime[p++]=i;
for(int j=2*i ; j<N ; j+=i)is_prime[j]=false;
}
}
}
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 m)
{
ll ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = multi(ans,a,m);
b--;
}
b >>= 1;
a = multi(a,a,m);
}
return ans;
}
void solve(ll A,ll B)
{
ll ans = 1;
for(int i=0; prime[i]*prime[i] <= A; i++)
{
if(A % prime[i] == 0)
{
int num = 0;
while(A%prime[i]==0&&(A/=prime[i]))
num++;
ll M = (prime[i] - 1) * MOD;
ans *= (quick_mod(prime[i],num*B+1,M) + M - 1) / (prime[i] - 1); //-1≡M-1(modM)
ans %= MOD;
}
}
if(A > 1)
{
ll M = MOD * (A - 1);
ans *= (quick_mod(A,B+1,M) + M - 1) / (A - 1);
ans %= MOD;
}
cout<<ans<<endl;
}
int main()
{
ll A,B;
sieve();
while(cin>>A>>B)
solve(A,B);
return 0;
}