题目:
题目链接:Sumdiv
题解:
题目就是在求
A
B
A^B%
AB的所有约数和在%mod。
一:整数的唯一分解定理:
A B A^B AB=( p 1 k 1 ∗ p 2 k 2 ∗ p 3 k 3 p_{1}^{k_1}*p_{2}^{k_2}*p_{3}^{k_3} p1k1∗p2k2∗p3k3…… p n k n p_{n}^{k_n} pnkn)B
= ( p 1 k 1 B ∗ p 2 k 2 B ∗ p 3 k 3 B p_{1}^{k_1B}*p_{2}^{k_2B}*p_{3}^{k_3B} p1k1B∗p2k2B∗p3k3B…… p n k n B p_{n}^{k_nB} pnknB)
二:约数和定理:
A B A^B AB=(1+ p 1 1 p_{1}^{1} p11+ p 1 2 p_{1}^{2} p12+……+ p 1 k 1 B p_{1}^{k_1B} p1k1B) ×(1+ p 2 1 p_{2}^{1} p21+ p 1 2 p_{1}^{2} p12+……+ p 2 k 2 B p_{2}^{k_2B} p2k2B)× ……×(1+ p n 1 p_{n}^{1} pn1+ p 1 n p_{1}^{n} p1n+……+ p n k n B p_{n}^{k_nB} pnknB)%mod
三、等比数列二分求和 :
注意上面的这句话:
(1+
p
1
1
p_{1}^{1}
p11+
p
1
2
p_{1}^{2}
p12+……+
p
1
k
1
B
p_{1}^{k_1B}
p1k1B)
就会发现这就是个等比数列,可是如果用等比数列求和公式就死掉了,不用试就炸掉了。
所以可以试一下二分求解:
1 + q + q2 + q3 = (1 + q2)+(q + q3) = (1 + q2)(1 + q)
下面就来推一下整个式子:
假设n是奇数:
1+q+……+qn(偶数个项) = (1 + qn/2+1)+(q + qn/2+2)……=(1+qn/2+1)(1 + q …… + qn/2)
假设n是偶数:
前面和n为奇数的情况是一样的,最后一项暴力得即可,(1+qn/2)qn/2
(这样的话就把复杂度直接降成log的了)
#include<bits/stdc++.h>
#define LL long long
#define mod 9901
using namespace std;
const int sea=10001;
int ans=1,k[sea],p[sea],n,a,b;
LL ksm(LL x,LL y)
{
LL s=1;
while(y)
{
if(y&1) s=(s*x)%mod;
y>>=1;
x=x*x%mod;
}
return s;
}
void ycl()//整数的唯一分解定理
{
n=0;
for(int i=2;i*i<=a;)
{
if(a%i==0)
{
p[++n]=i; k[n]=0;
while(!(a%i)) k[n]++,a/=i;
}
if(i==2) i++;
else i+=2;
}
if(a!=1) p[++n]=a,k[n]=1;
}
LL ysh(LL p,LL k)//等比数列二分求和
{
if(k==0) return 1;
if(k%2) return (ysh(p,k/2)*(1+ksm(p,k/2+1)))%mod;
else return (ysh(p,k/2-1)*(1+ksm(p,k/2+1))+ksm(p,k/2))%mod;
}
int main()
{
scanf("%d%d",&a,&b); ycl();
for(int i=1;i<=n;i++) ans=(ans*(ysh(p[i],k[i]*b)%mod))%mod;)//约数和定理
printf("%d\n",ans);
return 0;
}