这个专题将近过了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即为所求。


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 < 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


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 ;
}
优化后:


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 < 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 < 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 < 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 < 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 ;
}