Eddy's research I HDU - 1164(DFS大爆搜)

红红最近喜欢上了一个叫做素数的东西,她发现,所有的数都能够被分解成几个素数的乘积,可是她太懒了,所以想请你写一个程序来完成这个过程。
 

Input

多组输入数据,每组数据占一行,包含一个数x(1<x<=65535)

Output

在一行内输出符合题意的解(如果有多个素数因子则按字典序输出)

Sample Input

3
292

Sample Output

3
2*2*73

对于这类题目,我一开始没有什么思路,看到数据后,发现数据量不是很大,而且这个数据是由质数因子相乘得到的,我们就可以进行素数打表 ,和进行取余是否为0,进行剪枝。剪完枝后,时间就少了很多,就可以过了。代码:

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<bits/stdc++.h>
#include<set>
#include<vector>
#include<cmath>
const int maxn=100050;
using namespace std;
#include<map>
#include<string>
#include<string.h>
typedef long long ll;
typedef pair<int,int> p;

bool vis[maxn];	 
int Prime[maxn]; 
int cnt;
int n;
void fun()
{
	cnt = 0;
	memset(vis,true,sizeof(vis));
	vis[0] = vis[1] = false;	
	vis[2] = true;
	for(int i = 2 ; i<=maxn; i++)
	{
		if(vis[i])
		{
			Prime[cnt++] = i;
			for(int j = i+i ; j<=maxn; j+=i)
			{
				vis[j] = false;
			}

		}
	}
}


int a[maxn];
bool flag=false;


void dfs(int x,int now,int xiabiao,int i)
{
	if(x%now!=0)
		return ;
	if(flag)
		return ;
	if(now>x)
		return ;
	if(Prime[i]>x)
		return ;	
		
	if(now==x)
	{
		for(int j=0;j<xiabiao;j++)
		{
			if(j)
				cout<<"*";
			cout<<a[j];
			
		}
		flag=true;
		return ;
	}	
	
		
	a[xiabiao]=Prime[i];
		

	dfs(x,now*Prime[i],xiabiao+1,i+1);
	dfs(x,now*Prime[i],xiabiao+1,i);
	dfs(x,now,xiabiao,i+1);

	return ;
}


int main()
{
	fun();
	
	int x;
	while(scanf("%d",&x)!=EOF)
	{
		flag=false;
		dfs(x,1,0,0);
		
		cout<<endl;
	}
	return 0;
}

因为质数因子之间可以有重复的情况,所以我们需要三重DFS ,1.当前拿走 2.当前不拿走3.再拿走当前的一个 ,这个DFS 就好像是这几种方法,把这3个递归 放在一起,就是要让他们相互交错得到更多的结果。原理就是这样,理解了,代码就会很简单。一定要记得剪枝,不然TLE 到死。

然后就是打表的技巧,我们一定要记得,这样在你没有 模板的时候,也能拿分(蓝桥杯)。

上面是最傻的纯暴力解法,当你实在不会解题目时,你就可以使用大暴力,来拿一点样例分数。

下面我看看牛逼优秀的代码和思路:

#include<iostream>
using namespace std;
const int maxn=10000006;
typedef long long ll;
#include<bits/stdc++.h>
#include<map>
#include<set>
set<ll>s;


int cnt;
bool vis[maxn];
int prime[maxn];

void fun()
{
	cnt=0;
	memset(vis,true,sizeof(vis));
	vis[0]=vis[1]=false;
	vis[2]=true;
	for(int i=2;i<=maxn;i++)
	{
		if(vis[i])
		{
			prime[cnt++]=i;
			for(int j=i+i;j<=maxn;j+=i)
				vis[j]=false;	
		}	
	}
	
	//cout<<prime[cnt-1]<<endl;
}

int main()
{
	fun();
	ll n;
	while(cin>>n)
	{
			vector<int>s;
			ll num=n;
				
			for(ll i=0;prime[i]*prime[i]<=n;i++)
			{
				if(n%prime[i]==0)
				{
					while(n%prime[i]==0)
					{			
						n=n/prime[i];
						s.push_back(prime[i]);
					}
				}
				
			}
			if(n>1)
				s.push_back(n);
			
			for(int i=0;i<s.size();i++)
			{
				if(i)
					cout<<"*";
				cout<<s[i];
				
			}
				cout<<endl;
	}
	
	
	return 0;
}

我的这个素数相关知识不是很好,所以我先复习一下我的素数知识:这个素数判断是 从2一直到他的开根号的那个数据。(好菜啊我,一开始学C语言,老师就说过这个问题),我都没有在意这个。 

想一想,若2都不能除尽,还要试4, 6, 8, …吗?若3都不能除尽,还要试9, 15, 21, …吗?等等。一个数,如果有因子的话,那么在它的平方根数以内就应该有,否则就没有因子。所以必定有一个因子不大于m的平方根。故判断m是否为素数,只要试除到m的平方根就可以了,不必一直到m-1。
上面这个筛选素数因子,也是这样子,直接prime[i]*prime[i]<=m(这个数据),就把从一开始到这个 m数据,简化了一下,减少了一点时间。这个就是 在for 循环 内用了一个while循环,将所有这个的因子都除干净,然后再进行下一个素数的分解, 最后了再将最后一个除不尽的数据再加到 vector 中 ,最后输出。

还有一个题目 ,与这个是完全相同的写法,完全一样。   是个蓝桥被系统里面的一道题目:

问题描述

  给定一个正整数n,求一个正整数p,满足p仅包含n的所有素因子,且每个素因子的次数不大于1

输入格式

  一个整数,表示n

输出格式

  输出一行,包含一个整数p。

样例输入

1000

样例输出

10

数据规模和约定

  n<=10^12
  样例解释:n=1000=2^3*5*3,p=2*5=10

我就直接放代码吧:

#include<iostream>
using namespace std;
const int maxn=100005;
typedef long long ll;
#include<bits/stdc++.h>
#include<map>
#include<set>
set<ll>s;


int a[maxn];

int cnt;
bool vis[maxn];
int prime[maxn];

void fun()
{
	cnt=0;
	memset(vis,true,sizeof(vis));
	
	vis[0]=vis[1]=false;
	
	vis[2]=true;
	
	
	for(int i=2;i<=maxn;i++)
	{
		if(vis[i])
		{
			prime[cnt++]=i;
			for(int j=i+i;j<=maxn;j+=i)
				vis[j]=false;	
		}	
	}
}


int main()
{
	fun();
	ll n;
	cin>>n;
	ll sum=1;
	for(ll i=0;prime[i]*prime[i]<=n;i++)
	{
		if(n%prime[i]==0)
		{
			sum*=prime[i];
			while(n%prime[i]==0)
				n=n/prime[i];
		}
		
	}
	
	sum*=n;
	
	
	cout<<sum<<endl;
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/tsam123/article/details/88379313