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

2024-04-23 20:58
文章标签 dfs hdu research eddy 1164 大爆

本文主要是介绍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;
}

 

这篇关于Eddy's research I HDU - 1164(DFS大爆搜)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/929868

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时