HDU 2964 数论

题目的大致意思,就是说按照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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值