SGU 497
497. Abelian Groups
Time limit per test: 0.5 second(s)
Memory limit: 262144 kilobytes
Memory limit: 262144 kilobytes
input: standard
output: standard
output: standard
Andrew has just made a breakthrough in group theory: he realized that he can classify all finite Abelian groups (not much of a breakthrough, indeed). Given n, how many Abelian groups with n elements exist up to isomorphism? To help you solve this problem we provide some definitions and theorems from basic algebra (most are cited from Wikipedia). An abelian group is a set, A, together with an operation '·' that combines any two elements a and b to form another element denoted a · b. The symbol '·' is a general placeholder for a concretely given operation. To qualify as an abelian group, the set and operation, (A, ·), must satisfy five requirements known as the abelian group axioms:
- Closure: for all a, b in A, the result of the operation a · b is also in A.
- Associativity: for all a, b and c in A, the equation (a · b) · c = a · (b · c) holds.
- Identity element: there exists an element e in A, such that for all elements a in A, the equation e · a = a · e = a holds.
- Inverse element: for each a in A, there exists an element b in A such that a · b = b · a = e, where e is the identity element.
- Commutativity: for all a, b in A, a · b = b · a.
Input
First and only line of the input file contains an integer n, 1 ≤ n ≤ 1012.
Output
In the only line of the output file write the number of abelian groups with n elements.
Example(s)
sample input | sample output |
5
| 1
|
sample input | sample output |
4
| 2
|
sample input | sample output |
12
| 2
|
Online Contester Team © 2002 - 2010. All rights reserved. |
求n个元素构成的本质不同阿贝尔群。
有个公式:
N =p1^a1 * p2^a2 *......* pn^an
ans = P(a1)*P(a2)*...*P(an)
P(a) 表示a的划分数。
划分数可以用五边形定理解决,也可以暴力打表,注意到a不会超过50
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define nMax 1000010
// 筛质数
int p[nMax],a[nMax],pnum;
void init_p() {
pnum = 0;
int i,j,l=sqrt(nMax)+0.5;
for(i=2;i<=l;i++) if(!a[i]) {
p[pnum++] = i;
for(j=i*i;j<nMax;j+=i) a[j]=1;
}
for(;i<nMax;i++) if(!a[i]) p[pnum++]=i;
}
// 五边形数
int q[nMax][2],qnum;
void init_q(){
qnum=0;
while(1) {
q[qnum][0] = qnum*(3*qnum-1)/2;
q[qnum][1] = qnum*(3*qnum+1)/2;
if(q[qnum][1] >= 300) break;
qnum ++;
}
qnum++;
}
// 划分数
long long h[nMax];
int hnum;
void init_h(){
hnum = 200;
h[0]=1LL;
for(int i=1;i<hnum;i++){
h[i]=0LL;
for(int j=1;;j++) {
if(q[j][0]>i && q[j][1]>i) break;
if(q[j][0]<=i) {
if(j&1)
h[i] += h[i-q[j][0]];
else
h[i] -= h[i-q[j][0]];
}
if(q[j][1]<=i) {
if(j&1)
h[i] += h[i-q[j][1]];
else
h[i] -= h[i-q[j][1]];
}
}
}
}
#define bug puts("Oh It's Here");
void Init() {
init_p();
init_q();
init_h();
return ;
}
void sovle(long long n) {
long long ret = 1LL;
for(int i=0;i<pnum && p[i]<=n;i++) if(n%p[i]==0) {
long long a=0LL;
while(n%p[i]==0) {
a ++ ;
n /= p[i];
}
ret *= h[a];
}
cout<<ret<<endl;
}
int main() {
long long n;
Init();
while(cin>>n) {
sovle(n);
}
return 0;
}