LightOJ - 1050 (唯一分解+推公式+乘法逆元)
Posted 一个人的时光
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于LightOJ - 1050 (唯一分解+推公式+乘法逆元)的主要内容,如果未能解决你的问题,请参考以下文章
LightOJ 1341 Aladdin and the Flying Carpet(唯一分解定理)
[LightOJ 1341] Aladdin and the Flying Carpet (算数基本定理(唯一分解定理))