首页 > 代码库 > LightOJ - 1050 (唯一分解+推公式+乘法逆元)

LightOJ - 1050 (唯一分解+推公式+乘法逆元)

技术分享

题意:求a^b的所有约数和对1e9+7取模的结果

思路:对于一个数p,进行唯一分解,则p=P1^M1*P2^M2*...*Pn^Mn,则p的所有约数之和等于(P1^0+P1^1+...+P1^M1)*(P2^0+P2^1+...+P2^M2)*...*(Pn^0+Pn^1+...+Pn^Mn),

p^t=P1^(M1*t)*P2^(M2*t)*...*Pn^(Mn*t),每一个(Pn^0+Pn^1+...+Pn^Mn)利用等比数列可以直接推出公式为(Pn^(Mn*t+1)-1)/(Pn-1),用快速幂和乘法逆元即可。

注意:n的唯一分解只需要试遍sqrt(n)的所有质数即可,若最后n除不尽,那么最后的n一定是质数。

技术分享
  1 #include <iostream>
  2 #include <queue>
  3 #include <stack>
  4 #include <cstdio>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <string>
 14 #include <sstream>
 15 #include <time.h>
 16 #define x first
 17 #define y second
 18 #define pb push_back
 19 #define mp make_pair
 20 #define lson l,m,rt*2
 21 #define rson m+1,r,rt*2+1
 22 #define mt(A,B) memset(A,B,sizeof(A))
 23 using namespace std;
 24 typedef long long LL;
 25 const double PI = acos(-1);
 26 const int N=1e5+10;
 27 const LL mod=1e9+7;
 28 const int inf = 0x3f3f3f3f;
 29 const LL INF=0x3f3f3f3f3f3f3f3fLL;
 30 vector<LL> prime;
 31 int vis[N];
 32 void init()
 33 {
 34     mt(vis,0);
 35     LL m=sqrt(N+0.5);
 36     for(LL i=2;i<=m;i++)
 37     {
 38         if(!vis[i])for(LL j=i*i;j<=N;j+=i)vis[j]++;
 39     }
 40     for(LL i=2;i<N;i++)if(!vis[i])prime.pb(i);
 41 }
 42 void gcd(LL a,LL b,LL& d,LL& x,LL& y)
 43 {
 44     if(!b){d=a;x=1;y=0;}
 45     else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
 46 }
 47 LL inv(LL a,LL n)
 48 {
 49     LL d,x,y;
 50     gcd(a,n,d,x,y);
 51     return d==1?(x+n)%n:-1;
 52 }
 53 LL pow_mod(LL a,LL n)
 54 {
 55     LL res=1;
 56     while(n)
 57     {
 58         if(n&1)res=(res*a)%mod;
 59         a=(a*a)%mod;
 60         n/=2;
 61     }
 62     return res;
 63 }
 64 LL solve(LL a,LL n)
 65 {
 66     LL ans,p;
 67     ans=(pow_mod(a,n)-1+mod)%mod;
 68     p=inv(a-1,mod);
 69     return (ans*p)%mod;
 70 }
 71 int main()
 72 {
 73 #ifdef Local
 74     freopen("data.txt","r",stdin);
 75 #endif
 76     ios::sync_with_stdio(false);
 77     cin.tie(0);
 78     init();
 79     int T;
 80     LL n,m,ans;
 81     cin>>T;
 82     for(int d=1;d<=T;d++)
 83     {
 84         cout<<"Case "<<d<<":"<<" ";
 85         ans=1;
 86         cin>>n>>m;
 87         for(int i=0;i<prime.size()&&n!=1;i++)
 88         {
 89             int k=0;
 90             if(n%prime[i]==0)
 91             {
 92                 while(n%prime[i]==0)
 93                 {
 94                     n/=prime[i];
 95                     k++;
 96                 }
 97                 ans=(ans*solve(prime[i],(LL)(k*m+1)))%mod;
 98                 k=0;
 99             }
100         }
101         if(n>1)ans=(ans*solve(n,(LL)(m+1)))%mod;
102         cout<<ans<<endl;
103     }
104 #ifdef Local
105     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
106 #endif
107 }
View Code

 

LightOJ - 1050 (唯一分解+推公式+乘法逆元)