洛谷P1593 因子和
题目描述
输入两个正整数a和b,求a^b的因子和。结果太大,只要输出它对9901的余数。
输入输出格式
输入格式:仅一行,为两个正整数a和b(0≤a,b≤50000000)。
输出格式:a^b的因子和对9901的余数。
输入输出样例
输入样例#1:
2 3
输出样例#1:
15
看似不可做,其实非常简单
任意正整数都有且只有一种方式写出其素因子的乘积表达式。
A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)
其中 pi 均为素数
那么A^B=(p1^(k1*B))*(p2^(k2*B))*(p3^(k3*B))*....*(pn^(kn*B))
显然ans=∑i1∑i2.....∑ik(p1^i1)*(p2^i2)*.....(pk^ik)
=∑i1(p1^i1)∑i2(p2^i2).....∑ik(pk^ik)
但是k*B最大可以达到30000×50000000(极限估算)
这里我们运用指数取模的方法,因为模数很小
根据费马小定理,我们证出:
a^x≡a^(x%μ(p)) (mod p) μ(p)=9900,p=9901
这样我们发现,∑i(p^i)其实存在长度为μ(p)的循环节
这样,就算k*B再大,我们也可以通过O(μ(p))的求和处理算出循环节
然后就可以直接算出∑i(p^i)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long lol; 7 lol A,B,pri[100001],cnt[100001],ans,pw[1000001],tot; 8 int main() 9 {lol x,i,j; 10 cin>>A>>B; 11 x=A; 12 for (i=2;i*i<=A;i++) 13 { 14 if (x%i==0) 15 { 16 pri[++tot]=i; 17 while (x%i==0) 18 { 19 cnt[tot]++; 20 x/=i; 21 } 22 } 23 } 24 if (x!=1) 25 { 26 pri[++tot]=x; 27 cnt[tot]=1; 28 } 29 for (i=1;i<=tot;i++) 30 cnt[i]*=B; 31 ans=1; 32 for (i=tot;i>=1;i--) 33 { 34 pw[0]=1; 35 lol s=1,as=1; 36 for (j=1;j<=9899&&j<=cnt[i];j++) 37 { 38 pw[j]=pw[j-1]*pri[i]%9901; 39 s=(s+pw[j])%9901; 40 if (cnt[i]%9900==j) 41 as=s; 42 } 43 ans=(ans*((cnt[i]/9900)*s+as)%9901)%9901; 44 } 45 cout<<ans; 46 }