练习03:排序

A题:Big Number

     题意:求阶乘n的结果又多少位数。POJ的数据比hdu难过点,但是hdu讨论版的斯特林公式可以。我也不会证明,只能抄下来了咯。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#define Max 10000005
using namespace std;
int a[Max];//zhi
int b[Max];//
int ans[Max];
int main()
{
	int n,m;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d",&m);
		/*斯特林公式,使用log(i)+1会出现WA*/
		printf("%lld\n",(long long)((double)log10(sqrt(2*3.1415926535*m))+(double)m*log10(m/2.7182818284549))+1);
	}
	return 0;
}

B:

#include<stdio.h>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<queue>
#include<algorithm>
#include<map>

#define Max 210

using namespace std;
int node[Max][Max];
int MAX;
bool cmp(int a,int b)//xiao 
{
	return a>b;
}
int getmax(int a[],int n)//当前的MAX能不能满足所有的数组 
{
	int now_max=0;
	int max=0; 
	for(int i=0;i<n;i++)
	{
		if(a[i]>now_max)
		{
			max+=a[i]-now_max;//补上 
			now_max=a[i]-1; //给点
		}
		else
			now_max--;
	}
	return max;
}
int fun(int k)//第几个点,返回这个点的值 
{
	int temp[210];//临时使用 
	if(!node[k][0])//没有子孩子 
	{
		return 1;//
	 }
	for(int i=1;i<=node[k][0];i++)
	{
		temp[i-1]=fun(node[k][i]);
	}
	sort(temp,temp+node[k][0],cmp);//有多少个点
	return getmax(temp,node[k][0]);
}
int main()
{
	int n,m,k,i,j;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d",&m);
		MAX=0;
		memset(node,0,sizeof(node));
		while(m--)
		{
			scanf("%d%d",&k,&j);
			node[k][0]=j;//记录有多少个点 
			for(int i=1;i<=j;i++)
			{
				scanf("%d",&node[k][i]);
			}
		}
		printf("%d\n",fun(1));
	}
	return 0;
}

 

C:Monkeys' Pride

  求有多少个点,没有其他点的X和Y同时大于或等于这个点。先把所有点的X排序(X相同Y大的大),然后从X最大的点开始往下遍历,发现一个Y大于当前最大的Y(从最大的X的Y开始到最小的X),则表示这个点可以,sum++;理由:因为X从大到小遍历。当前的X比没有遍历的点都大,且当前的Y比已经遍历的点的Y都大,所以不存在同时大于该点X,Y的点。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define Max 50050
using namespace std;

struct Node {
	int x;
	int y;
}a[Max];
bool cmp(Node a,Node b)//大》小 
{
	if(a.x!=b.x)
		return a.x>b.x;
	else
		return a.y>b.y;
}
int main()
{
	int x,y;
	int Max_x=0,Max_y=0;
	int n;
	while(scanf("%d",&n)!=EOF&&n)
	{
		Max_x=0,Max_y=0;
		memset(a,0,sizeof(a)); 
		for(int i=0;i<n;i++)
		{
			scanf("%d%d",&a[i].x,&a[i].y);
		}
		sort(a,a+n,cmp); //排序 
		int ans=1,max_y=a[0].y,max_x=a[0].x;
		for(int i=1;i<n;i++)
		{
			if(a[i].x==max_x) //x已经是最大的 
				continue;
			else if(a[i].y>max_y) //目前的X最大,发现Y大于最大的,ans++ 
			{
				ans++;
				max_y=a[i].y;
			 } 
		}
		printf("%d\n",ans);
	}
	return 0;
}

D:排列

求后面第K个字典序,使用STL的next_permutation水过,,但是注意提交要用C++提交,G++会迷之超时~。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define Max 1030
using namespace std;
/*g++会超时,C++不会超时*/
int a[Max];
int main()
{
	int n;
	scanf("%d",&n);
	int m,k;
	while(n--)
	{
		scanf("%d%d",&m,&k);
		for(int i=0;i<m;i++)
		{
			scanf("%d",&a[i]);
		}
		while(k--)
		{
			next_permutation(a,a+m); //求下个字典序,会改变原来字符的位置
		}
		for(int i=0;i<m;i++)
		{
			printf("%d",a[i]);
			if(i!=m-1)
				printf(" ");
			else
				printf("\n");
		}
	}
	return 0;
}

F:Ultra-QuickSort ;J 题同理

就是求逆序对,使用并归排序求逆序对。不过J题可以直接使用两个for暴力通过。

G - Word Amalgamation

构建一个字典,然后枚举字符串的排列组合,发现一样的就输出(还以为必须要用字典树.....)还是使用map。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#define Max 105
#define max(a,b) a>b?a:b;
#define min(a,b) a>b?b:a;

using namespace std;
map<string, bool> m;
int main()
{
	int n=0;
	char temp[10];
	string word;
	while(scanf("%s",temp)&&strcmp("XXXXXX",temp))
	{
		word=temp;
		m[word]=true;
	}
	while(scanf("%s",temp)&&strcmp("XXXXXX",temp))
	{
		char laji[10];
		int flag=0;
		int len=strlen(temp);
		sort(temp,temp+strlen(temp));//从小到大
		//然后暴力枚举 next_permutation
		word=temp;
		strcpy(laji,temp);
		if(m[word])
		{
			printf("%s\n",temp);
			flag=1;
		}
		while(1)
		{
			next_permutation(temp,temp+len);
			if(strcmp(temp,laji)==0)  //全部枚举完了
			{
				break;
			}
			word=temp;
			if(m[word])//有就输出
			{
				flag=1;
				printf("%s\n",temp);
			}
		}
		if(!flag)
			printf("NOT A VALID WORD\n");
		printf("******\n");
	}
	return 0;
}

H:就是求中位数;K 排序就好了,快排排序然后直接输出。

I:487-3279

好像可以用字典树写,求号码转化后有多少个。大于1就直接输出。我用map水过(提交C++才能过,G++超时,迷*2)

mapC++里面的,不懂的百度。

#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<map> 
#include<queue>
#include<iostream>
#define Max 100010
using namespace std;
//先把键盘和数字对应保存下来
char tab[]={'2','2','2','3','3','3','4','4','4','5','5','5','6','6','6','7','7','7','7','8','8','8','9','9','9','9'};
map<string ,int > m;//字典
struct Node{
	string tel;
	int n;
}all[Max];
bool cmp(Node one,Node two) //大》》小 
{
	return one.tel<two.tel;
}
int main()
{
	int n;
	scanf("%d",&n);
	char tel[100];
	char ph[10];
 string TEL;
	for(int i=0;i<n;i++)
	{
  scanf("%s",tel);
		memset(ph,'\0',sizeof(ph));
		int count=0;
		for(int i=0;tel[i];i++) //转化为数字
		{
			if(tel[i]=='-')
				continue;
			if(tel[i]<='9')//数字
			{
				ph[count++]=tel[i];
			}
			else
			{
				ph[count++]=tab[tel[i]-'A'];
			}
		}
		ph[count]='\0';
		TEL=ph;
  if(m[TEL]) //已经存在
		{
			m[TEL]+=1;
		}
		else
		{
			m[TEL]=1;
		}
	 }

	map<string ,int >::iterator i;
	i=m.begin();
	int flag=0;
	int Count=0;
 while(i!=m.end()) //map 迭代遍历,根据字典树顺序来的,所以不用排序了
	{
		if(i->second>1)
		{
           flag=1;
			string temp=i->first;
			for(int j=0;temp[j];j++)
			{
				if(j!=2)
				{
					printf("%c",temp[j]);
				}
				else
					printf("%c-",temp[j]);
			}
			printf(" %d\n",i->second);
		}
		i++;
	}
	if(!flag)
	{
		printf("No duplicates.\n");
		return 0;
	}
	return 0;
}

L - Babelfish

这题应该是哈希函数吧,额,我选择还是用map写(内部好像是红黑树,效率蛮高的)。

这题应该考手写哈希吧,水题。

#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<map> 
#include<queue>

using namespace std;
map<string, string> m;//使用字典 

int main()
{
	char a[15],b[15];
	string ac,wa;
	while(1)
	{
		int i;
		memset(a,'\0',sizeof(a));
		memset(b,'\0',sizeof(b));
		scanf("%c",&a[0]);
		if(a[0]=='\n') 	//完结 
			break; 
		for(i=1;1;i++)
		{
			scanf("%c",&a[i]);
			if(a[i]==' ') //空格 
				break;
		}
		a[i]='\0';
		scanf("%s",b);
		getchar();//吸收回车 
		ac=a;
		wa=b;
		m[wa]=ac; //构建字典 
	}
	while(scanf("%s",a)!=EOF)
	{
		wa=a;
		if(m.find(wa)!=m.end()) //在
		{
			cout<<m[wa]<<endl;
		}
		else
		{
			printf("eh\n");
		}
	}
	return 0;
}

还有两题也是水题,就不写了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值