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;
}
求有多少个点,没有其他点的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暴力通过。
构建一个字典,然后枚举字符串的排列组合,发现一样的就输出(还以为必须要用字典树.....)还是使用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;
}
还有两题也是水题,就不写了。