# 洛谷P1593 因子和 & POJ1845 Sumdiv

POJ题目传送门

$a=\prod_{i=1}^m p_i^{c_i}\left(c_i\in\mathbb{Z^+}\right)$

$\left(p_1^0+p_1^1+p_1^2+\cdots+p_1^{c_1}\right)\left(p_2^0+p_2^1+p_2^2+\cdots+p_2^{c_2}\right)\cdots\left(p_m^0+p_m^1+p_m^2+\cdots+p_m^{c_m}\right)$

$\prod_{i=1}^m \sum_{j=0}^{c_i} p_i^j$

\begin{align*} a^b &=\left(\prod_{i=1}^m p_i^{c_i}\right)^b\\ &=\prod_{i=1}^m p_i^{bc_i}\end{align*}

$\prod_{i=1}^m \sum_{j=0}^{bc_i} p_i^j$

$\sum_{j=0}^{bc_i} p_i^j=\frac{p_i^{bc_i+1}-1}{p_i-1}$

$p_i^{bc_i+1}-1$ 可以用快速幂，因为这道题要取模，所以需要搞一下 $p_i-1$ 的逆元。

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5e7+10;
const int MOD=9901;
int qpow(int a,int n,int m)
{
int base=a%m,ans=1;
while(n)
{
if(n&1) ans=(ans*base)%m;
base=(base*base)%m;
n>>=1;
}
return ans;
}
int a[N],c[N],n,b,cnt=0;
void init()
{
int i=2;
while(n>1)
{
if(!(n%i))
{
n/=i;
a[++cnt]=i;
c[cnt]=1;
while(!(n%i))
{
n/=i;
c[cnt]++;
}
}
i++;
if(i*i>n) break;
}
if(n>1)
{
a[++cnt]=n;
c[cnt]++;
}
}
int inv(int s,int p) {return qpow(s,p-2,p);}
int main()
{
scanf("%d %d",&n,&b);
init();
int ans=1;
for(int i=1;i<=cnt;i++)
{
int z=c[i]*b+1;//指数
int in=inv(a[i]-1,MOD);//inv(a-1)
int s=(qpow(a[i],z,MOD)-1+MOD)%MOD;
s=(s*in)%MOD;
ans=(ans*s)%MOD;
}
printf("%d",ans);
}


\begin{align*}\left(\sum_{j=0}^{bc_i} p_i^j\right)\bmod 9901 &=\left(\sum_{j=0}^{bc_i} \left(p_i^j\bmod 9901\right)\right)\bmod 9901\\&=\left(\sum_{j=0}^{bc_i} 1\right)\bmod 9901\\&=\left(bc_i+1\right)\bmod 9901\end{align*}

AC code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5e7+10;
const int MOD=9901;
int qpow(int a,int n,int m)
{
int base=a%m,ans=1;
while(n)
{
if(n&1) ans=(ans*base)%m;
base=(base*base)%m;
n>>=1;
}
return ans;
}
int a[N],c[N],n,b,cnt=0;
void init()
{
int i=2;
while(n>1)
{
if(!(n%i))
{
n/=i;
a[++cnt]=i;
c[cnt]=1;
while(!(n%i))
{
n/=i;
c[cnt]++;
}
}
i++;
if(i*i>n) break;
}
if(n>1)
{
a[++cnt]=n;
c[cnt]++;
}
}
int inv(int s,int p) {return qpow(s,p-2,p);}
int main()
{
scanf("%d %d",&n,&b);
init();
int ans=1;
for(int i=1;i<=cnt;i++)
{
if((a[i]-1)%MOD)
{
int z=c[i]*b+1;//指数
int in=inv(a[i]-1,MOD);//inv(a-1)
int s=(qpow(a[i],z,MOD)-1+MOD)%MOD;
s=(s*in)%MOD;
ans=(ans*s)%MOD;
}
else ans=ans*(b%MOD*c[i]+1)%MOD;
}
printf("%d",ans);
}


posted @ 2020-05-15 09:47  zzt1208  阅读(116)  评论(0编辑  收藏