POJ 刷水
这个专题将近过了10天了吧,这个.doc文件一直存到电脑里,我就把它发出来吧。
1004, 1003, 1005, 1006, 1007, 1002, 1001, 1008, 1163, 1088,
2027, 1012, 1046, 1050, 1207, 2000, 1218, 1664, 1011, 1013
北大OJ:http://124.205.79.250/JudgeOnline
12个浮点数求平均值。
根据题意求和1/2 + 1/3 + 1/4 + ... + 1/(i+ 1)
直到sum >=n,结束循环,i-2即为所求。
#include<stdio.h>
int main()
{
int i;
double n,t,sum;
while(scanf("%lf",&n))
{
if(n==0.00)
break;
t=0;
i=1;
sum=0;
while(sum<n)
{
sum+=t;
i++;
t= 1.0 / i;
}
printf("%d card(s)\n",i-2);
}
return 0;
}
题目大意:陆地每年被侵蚀50平方英里,给定房子的坐标,求其第几年被侵蚀。(侵蚀从坐标原点开始)。
实现方法:years从1开始累加,由每年的半圆面积求出被侵蚀的半径,直到给定的点被侵蚀结束循环。
#include<stdio.h>
#include<math.h>
#define PI acos(-1.0)
int main()
{
int n,i,years;
double x,y,dissqu;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lf%lf",&x,&y);
dissqu=x*x+y*y;
for(years=1;100*years<PI*dissqu;years++);
printf("Property %d: This property will begin eroding in year %d.\n",i,years);
}
puts("END OF OUTPUT.");
return 0;
}
生物节律,给出该年内每个属性(physical, emotional or mental)出现峰值的天数,然后计算出各个属性都达到峰值的天数(从给定的天数开始算起)。如果按照题意一步步循环,跑了766MS,优化以后跑63MS
几组数据,很牛啊:
0 4 5 0 368
2 2 2 2 21252
123 128 133 1 99
123 128 133 100 21252
0 1 2 1 16996
1 0 2 1 8119
1 2 0 1 13133
1 2 3 0 16998
117 58 2 27 21227
#include<stdio.h>
int main()
{
int p,e,i,d,cas=1,k;
while(scanf("%d%d%d%d",&p,&e,&i,&d) && p+e+i+d!=-4)
{
for(k=d+1;k<=21252+d;k++)
{
if((k-p)%23!=0)
continue;
else{
if((k-e)%28!=0)
continue;
else{
if((k-i)%33!=0)
continue;
}
}
break;
}
printf("Case %d: the next triple peak occurs in %d days.\n",cas,k-d);
cas++;
}
return 0;
}
优化后:
#include<stdio.h>
int main()
{
int p,e,i,d,cas=1,k;
while(scanf("%d%d%d%d",&p,&e,&i,&d),p+e+i+d!=-4)
{
for(k=i%33; ;k+=33)
{
if((k-p)%23==0 && (k-e)%28==0 && k>d)
break;
}
printf("Case %d: the next triple peak occurs in %d days.\n",cas++,k-d);
}
return 0;
}
按题意对每个串的无序程度升序排序,无序程度相等的按输入次序升序排序。
#include<stdio.h>
#include<stdlib.h>
struct DNA{
int num;
char s[52];
int unsorted;
}dna[102];
int n;
int cmp(const void *a,const void *b)
{
struct DNA *c=(struct DNA *)a;
struct DNA *d=(struct DNA *)b;
if(c->unsorted!=d->unsorted)
return c->unsorted - d->unsorted;
return c->num - d->num;
}
int UNSorted(char s[52])
{
int i,j,ans=0;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(s[i]>s[j])
ans++;
return ans;
}
int main()
{
int m,i;
while(scanf("%d%d",&n,&m)!=EOF){
getchar();
for(i=0;i<m;i++){
gets(dna[i].s);
dna[i].num=i;
dna[i].unsorted=UNSorted(dna[i].s);
}
qsort(dna,m,sizeof(dna[0]),cmp);
for(i=0;i<m;i++)
puts(dna[i].s);
}
return 0;
}
找出重复的电话号码,附带两组数据。我的方法是先开一个10000000大的数组,对每个翻译成数字的电话号码进行标记(加1),输出出现次数大于1的号码及次数。没有重复输出"No duplicates."。这个方法跑了688MS,有待优化啊。
4
0000000
0010001
0000000
0010001
2
0000000
0010001
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
int mark[10000000];
int main()
{
int n,t,i,num,flag;
char s[50];
int match[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9,0};
memset(mark,0,sizeof(mark));
scanf("%d",&n);
getchar();
while(n--)
{
gets(s);
t=6;
num=0;
for(i=0;s[i];i++)
{
if(isupper(s[i]))
num+=match[s[i]-'A']*(int)pow(10.0,t--);
if(isdigit(s[i]))
num+=(s[i]-'0')*(int)pow(10.0,t--);
}
mark[num]++;
}
flag=0;
for(i=0;i<=9999999;i++)
{
if(mark[i]>1)
{
printf("%03d-%04d %d\n",i/10000,i%10000,mark[i]);
flag=1;
}
}
if(flag==0)
puts("No duplicates.");
return 0;
}
看了清华大学的《程序设计导引及在线实践》,有这道例题,438MS A掉了
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char map[]="22233344455566677778889999";
char str[80],telNumbers[100000][9];
int cmp(const void *a,const void *b)
{
return strcmp((char *)a,(char *)b);
}
void standardizeTel(int n){
int j, k;
j = k = -1;
while(k <8)
{
j ++;
if(str[j] == '-')
continue;
k ++;
if(k == 3)
{
telNumbers[n][k] = '-';
k ++;
}
if(str[j] >= 'A' && str[j] <='Z'){
telNumbers[n][k] = map[str[j]-'A'];
continue;
}
telNumbers[n][k]=str[j];
}
telNumbers[n][k] = '\0';
return;
}
int main()
{
int n, i, j;
bool noduplicate;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",str);
standardizeTel(i);
}
qsort(telNumbers,n,sizeof(telNumbers[0]),cmp);
noduplicate = true;
i = 0;
while(i < n)
{
j = i;
i ++;
while(i < n && strcmp(telNumbers[i],telNumbers[j])==0) i ++;
if(i - j >1){
printf("%s %d\n",telNumbers[j],i - j);
noduplicate = false;
}
}
if(noduplicate)
puts("No duplicates.");
return 0;
}
这一题大整数相乘,还带小数点。要考虑的情况很多,处理起来不是很容易啊。
0.0100 2
4.00 2
10.00 2
10 2
#include<stdio.h>
#include<string.h>
#define N 1500
void rev(char a[N]) //字符串倒置函数,POJ不支持strrev库函数
{
char b[N];
int i,len=strlen(a);
for(i=0;i<len;i++)
b[i]=a[len-1-i];
b[i]='\0';
strcpy(a,b);
}
void mul(char a[N],char b[N]) //a和b相乘,结果存入b中
{
char c[N];
int temp[N]={0};
int i,j,k,carry,len1,len2;
rev(a);
rev(b);
len1=strlen(a);
len2=strlen(b);
for(i=0;i<len1;i++)
{
k=i;
for(j=0;j<len2;j++)
temp[k++]+=(a[i]-48)*(b[j]-48);
}
carry=0;
for(i=0;i<k;i++)
{
temp[i]+=carry;
carry=temp[i]/10;
c[i]=temp[i]%10+48;
}
if(carry>0)
c[i++]=carry+48;
c[i]='\0';
rev(c);
strcpy(b,c);
rev(a);
}
int main()
{
char a[N],b[N],c[N];
int i,j,len,n,m,num;
while(scanf("%s%d",a,&n)==2)
{
num=0;
len=strlen(a);
for(i=0;i<len;i++) //找到并记下小数点的位置,并把它去点
{
if(a[i]=='.')
{
len--;
num=len-i;
for(;i<len;i++)
{
a[i]=a[i+1];
}
a[i]='\0';
break;
}
}
j=0;
for(i=0;i<len-1;i++) //消除串a的前导'0'
{
if(a[i]!='0')
{
for(;i<len;i++)
{
a[j++]=a[i];
}
a[j]='\0';
break;
}
}
m=n;
strcpy(b,"1");//初始化b
while(n) //这里用到快速幂取模,用n的二进制形式求幂结果
{
if(n%2)
mul(a,b);
strcpy(c,a);
mul(c,a);
n/=2;
}
len=strlen(b); //求得结果存入b
num*=m; //num为b中小数点位置,从后向前查
if(num!=0)
{
if(num<=len)
{
for(i=len;i>len-num;i--)
b[i]=b[i-1];
b[i]='.';
b[++len]='\0';
}
if(num>len) //如果b的位数不够,这前面补'0',用以加小数点
{
for(i=num,j=len-1;i>num-len;i--,j--)
b[i]=b[j];
b[++num]='\0';
for(i=1;i<num-len;i++)
b[i]='0';
b[0]='.';
len=num;
}
for(i=len-1;i>0;i--) //消掉小数末尾的'0'
{
if(b[i]!='0')
break;
else
{
len--;
b[i]='\0';
}
}
}
if(b[len-1]=='.') //如果小数点后面全是'0',小数点也要去掉
{
b[len-1]='\0';
len--;
}
puts(b);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
}
return 0;
}