洛谷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=∑i1i2.....∑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 }

 

posted @ 2017-10-19 14:41  Z-Y-Y-S  阅读(336)  评论(0编辑  收藏  举报