a题 数字的序数。数字末带“1”、“2”,“3”的一般加“st”、“nd”、“rd”但是以“11”、“12”、“13”结尾的加“th”,其他的都是加“th”。
#include <stdio.h>
int main()
{
int t,n;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
if (n%10==1 && n%100!=11)
printf("%dst\n",n);
else if (n%10==2 && n%100!=12)
printf("%dnd\n",n);
else if (n%10==3 && n%100!=13)
printf("%drd\n",n);
else printf("%dth\n",n);
}
return 0;
}
b题,判断各个函数的特殊情况。
#include <stdio.h>
int main()
{
double a,b,c,d,e,f;
int t;
scanf("%d",&t);
while (t--)
{
scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f);
if (a==c)
printf("circle\n");
else if (a==0||c==0)
printf("parabola\n");
else if (a*c<0)
printf("hyperbola\n");
else
printf("ellipse\n");
}
return 0;
}
d题。模拟。zoj上不支持strrev。ce几次。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define swap(x,y,z) ((z)=(x),(x)=(y),(y)=(z))
void move(char *s,int pos)
{
int i,len=strlen(s);
s[len+1]='\0';
for (i=len-1;i>=pos;i--)
s[i+1]=s[i];
}
int no_alnum(char *s)
{
int i;
for (i=0;i<strlen(s);i++)
if (isalnum(s[i]))
return 0;
return 1;
}
void deal(char *s)
{
int i,j,k,l,m,n,len=strlen(s),flag=1,f;
for (i=0;i<len;i++)
{
f=1;
if (isalnum(s[i]))
{
if (s[i]=='Z'||s[i]=='z'||s[i]=='9')
{
if (s[i]=='Z') {s[i]='A'; }
if (s[i]=='z') {s[i]='a'; }
if (s[i]=='9') {s[i]='0'; }
if (no_alnum(s+i+1)&&isupper(s[i])) {move(s,i+1);s[i+1]='A';f=0;}
if (no_alnum(s+i+1)&&islower(s[i])) {move(s,i+1);s[i+1]='a';f=0;}
if (no_alnum(s+i+1)&&isdigit(s[i])) {move(s,i+1);s[i+1]='1';f=0;}
if (f) deal(s+i+1);
}
else s[i]++;
flag=0;
break;
}
}
if (flag) s[0]++;
}
int main()
{
int t;
char s[110],tmp;
int c,i,len;
scanf("%d",&t);
while (t--)
{
scanf("%s%d",s,&c);
while (c--)
{
len=strlen(s);
for (i=0;i<len/2;i++)
swap(s[i],s[len-i-1],tmp);
//strrev(s);
deal(s);
len=strlen(s);
//strrev(s);
for (i=0;i<len/2;i++)
swap(s[i],s[len-i-1],tmp);
printf("%s\n",s);
}
printf("\n");
}
return 0;
}
F题。把数列排成一个圆,求对面那个数。
#include <stdio.h>
#include <string.h>
char s[105][25];
int main()
{
int t,i,n,k;
char fin[25];
scanf("%d",&t);
while (t--)
{
scanf("%d%s",&n,fin);
for (i=0;i<n;i++)
{
scanf("%s",s[i]);
if (strcmp(s[i],fin)==0)
k=i;
}
printf("%s\n",s[(k+n/2)%n]);
}
return 0;
}
L题。数学题。
纸老虎题,有n个盒子,第i个盒子里有i个东西,每次选取一些盒子,然后从这些盒子中每个都取出相同数目的东西。问至少几次可以把盒子清空?
把每个盒子看成集合。有n个集合,分别有1…n个元素。具体每种集合有多少个是没意义的,因为我们可以把具有相同元素的集合同时操作,所以我们可以用集合的种类代替集合的个数。假设,每次选取k个集合。从这k个集合里拿东西,则这k个集合拿过之后还是k个不同的集合(有可能有一个成空集),所以至少还有(k-1)个不同的集合,而除这k个外还有(n-k)个不同的集合。所以拿完之后不同集合的个数至少变为了r=max(k-1,n-k)。考虑当n是偶数时当k=n/2时,r取最小值,max(k-1,n-k)=n/2,当n为奇数时,k=(n+1)/2时,r取最小值max(k-1,n-k)=(n-1)/2。这个最小值是剩余集合数的一个下界。
其实这个下界是可以达到的:
n是偶数时,从元素个数不少于n/2的全部集合里都拿n/2个,则,剩余集合元素个数变为了1,2……n/2,问题规模缩小了一半。
n是奇数时,从元素个数不少于(n+1)/2的集合里都拿(n+1)/2个,则剩余集合元素个数变为了1,2,…(n-1)/2,问题规模也缩小了一半。
而在c语言中,除以2是下取整的,所以无论n为奇数还是偶数,一次操作之后集合个数至少变成了n/2,并且有办法可以达到这个最小值。
于是,最少拿的次数就是每次把n不断除以2,除到0为止。即n的2进制表示中的bit数。
#include <stdio.h>
typedef unsigned int uint;
uint a[33];
int main()
{
int t;
uint i,n;
a[0]=1;a[1]=2;
for (i=2;i<33;i++)
a[i]=2*a[i-1];
scanf("%d",&t);
while (t--)
{
scanf("%u",&n);
for (i=1;i<33;i++)
if (n>=a[i-1]&&n<a[i])
{printf("%u\n",i);break;}
}
return 0;
}
M题。求中值。
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a,const void *b)
{
return (*(double *)a)>(*(double *)b)?1:0;
}
double a[1000];
int main()
{
int t,i,n;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
for (i=1;i<=n;i++)
scanf("%lf",&a[i]);
qsort(a+1,n,sizeof(a[0]),cmp);
if (n%2) printf("%.3lf\n",a[n/2+1]);
else printf("%.3lf\n",(a[n/2]+a[n/2+1])/2.0);
}
return 0;
}