首先要预处理求出素数
void Euler_prim(int n)
{
//欧拉筛选法 避免上面筛选法中的重复筛选
memset(check,false,sizeof(check));
int tot = 0;
for(int i = 2;i <= n;i ++)
{
if(!check[i]) prim[tot ++] = i;
for(int j = 0;j < tot;j ++) //遍历已经找到的素数
{
if(i * prim[j] > n) break; //后面相乘已经超出 n 的范围,没有查找的必要了
check[i * prim[j]] = true; //表示这个数字不是素数
if(i % prim[j] == 0) break;
}
}
}
再写一个快速幂取模:
int PowerMod(int a, int b, int c)
{
int ans=1;
a=a%c;
while(b>0) {
if(b%2==1)
ans=(ans*a)%c;
b=b/2;
a=(a*a)%c;
}
return ans;
}
再进行分解:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
bool check[100005];
int prime[100005]; //储存第i个素数
int tot=0;
LL pow(LL a, LL n, LL p) //快速幂 a^n % p
{
LL ans = 1;
while(n)
{
if(n & 1) ans = ans * a % p; //若不取模就去掉p
a = a * a % p;
n >>= 1;
}
return ans;
}
void getprime(int n)
{
memset(check, 0, sizeof(check)); // 标记数组初始化,初始均为 0
tot = 0; // tot 初始为 0,用来记录质数总个数
for (int i = 2; i <= n; ++i) { // 从 2 开始枚举
if (!check[i]) { // 如果 i 没有被划去,则 i 为质数,加入质数表中
prime[++tot] = i;
}
for (int j = 1; j <= tot; ++j) { // 划去 i 与所有已筛出的质数的乘积
if (i * prime[j] > n) { // 判断合数是否在区间内
break;
}
check[i * prime[j]] = 1; // 划去在区间内的合数
if (i % prime[j] == 0) { // 保证合数只被其最小的质因子划去,提高筛选效率
break;
}
}
}
}
void getans(int n)
{
int a[10000],b[100005],c[100005],cnt=0,cnt2=0,t;
t=n;
for(int i=1;prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
a[cnt]=prime[i];
while(n%prime[i]==0)
{
c[cnt2++]=prime[i];
b[cnt]++;
n/=prime[i];
}
cnt++;
}
}
if(n!=1)
{
a[cnt]=n;
b[cnt]=1;
c[cnt2]=n;
cnt2++;
cnt++;
}
int cnt_factor=1; //因数的个数
long long sum_factor=1; //全部因数之和
for(int i=0;i<cnt;i++)
cnt_factor*=(b[i]+1);
cout<<cnt_factor<<endl; //因数的个数
for(int i=0;i<cnt;i++)
{
LL cur=0;
for(int j=0;j<=b[i];j++)
{
cur+=pow(a[i],j,mod);
}
sum_factor*=cur;
}
cout<<sum_factor-t<<endl; //全部因数之和((除了n本身)
for(int i=0;i<cnt;i++) //幂指形式表示
cout<<a[i]<<"^"<<b[i]<<" ";
cout<<endl;
for(int i=0;i<cnt2;i++) //连乘形式表示
cout<<c[i]<<" ";
cout<<endl;
}
int main()
{
int n;
getprime(10000);
scanf("%d",&n);
getans(n);
return 0;
}