题目的大致意思,就是说按照n = a0 + a1*p0 + a2*p0*p1 + a3*p0*p1*p2 + ... 这样的形式把n进行分解,pi是素数。已知,ai就是每一项素数相乘的系数。这道题目应该从后面往前面想,先找到<=n最大的素数的乘积,然后再往小了算,并且依次算出每一项的系数,已经相乘的素数的个数,到输出的时候会用的到。
那么现在我们要做的任务有以下几点:
1。打素数表,并且把逐个素数相乘的结果存在一个数组中。例如2 2*3 2*3*5.....
因为题目当中的n是32位整数,所以,素数相乘到第9个的时候就已经溢出了,所以没必要单独写函数去打素数表,直接在创建数组的时候初始化即可。
2,求出每一项的系数,即ai,以及所乘素数的个数,并存在数组里面
3,输出。
素数的数组和乘积的数组都不用担心,关键是每一项的系数和素数个数。
再求系数的时候,我们首先要找到最大的《=n的素数乘积的值,然后用n除以这个乘积得到该项的系数,然后n对这个乘积的值去余,即去掉了已经求得
的部分,分解剩下的部分。但是这时候要注意的是,每一次寻找的时候都要从乘积数组的头部开始。、
这样把对应的系数和个数都存到相应的数组中,到最后直接从当前的下表开始进行输出,直到下标为0;
求个数的时候,通过下面的这个图就可以直到怎么求了(^_^);
需要注意的是,如果n在乘积数组中找到与之对应相等的值,那么这种情况要单独考虑,具体请参照代码;
4,在输出的时候,如果始终n的值已经n不断去余过程中的数值找不到与乘积数组当中的值相等的时候,即会最后剩下一个1无法分解,这个时候,就会出现两种情况,一种n==0即找到相等的在乘积数组中,另一种n==1,没有找到,即有一个1最后不能分解,这就是循环的终点。
话不多说,代码如下
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<cmath>
#define LL long long
int prime[100];
LL chengji[100];
bool vis[100];
void creat()
{
int i,j,k;
int temp;
double m;
j=1;
for(i=2;i<=10;i++)
{
if(!vis[i])
{
vis[i]=true;
prime[j++]=i;
for(k=i+i;k<=100;k=k+i)
vis[k]=true;
}
}
for(i=11;i<=100;i++)
{
if(!vis[i])
prime[j++]=i;
}
}
void jisuan()
{
int i,j,k;
LL sum=1;
chengji[0]=1;
j=1;
for(i=1;i<100;i++)
{
sum*=prime[i];
chengji[j++]=sum;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("f:\\in.txt","r",stdin);
#endif
int i,j,k,m,t;
__int64 xishu[100];
__int64 xiangshu[100];
int n;
int temp;
while(scanf("%d",&n)&&n)
{
temp=n;
memset(vis,0,sizeof(vis));
memset(prime,0,sizeof(prime));
memset(xishu,0,sizeof(xishu));
memset(xiangshu,0,sizeof(xiangshu));
creat();
jisuan();
for(i=0,j=0;i<100;i++)
{
if(chengji[i]>n)
{
xishu[j]=n/chengji[i-1];
xiangshu[j]=i-1;
n=n%chengji[i-1];
i=-1; //每次再找分解式子中的下一项的时候都要在chengji数组的头部开始//
if(n==1)
break;
j++;
}
if(chengji[i]==n)
{
xishu[j]=n/chengji[i];
xiangshu[j]=i;
n=n%chengji[i];
i=-1;
if(n==0)
break;
j++;
}
}
printf("%d = ",temp);
if(n==1) //只剩下1,不能再继续分解//
printf("1 + ");
for(t=j;t>=0;t--)
{
printf("%I64d",xishu[t]);
for(i=1;i<=xiangshu[t];i++)
printf("*%d",prime[i]);
if(t!=0)
printf(" + ");
}
printf("\n");
}
return 0;
}