您的位置:首页 > 其它

算法竞赛入门学习

2012-10-22 23:45 267 查看
学习目标:

学会用常量表简化代码、学会用状态变量辅助字符串的读入、冒泡排序、顺序检索、qsort库函数针对整数和字符串排序的方法、小规模素数表的构造方法、因子分解、三角形有向面积的计算方法和意义。

5.1.1 WERTYU

把手放在键盘上时,稍不注意就会往右错一位。这样的话,Q会变成W,J会变成K等。

输入一个错位后敲出的字符串,输出打字员本来想打出的句子

样例输入:O S, GOMR YPFSU/

样例输出:I AM FINE TODAY.
#include <stdio.h>
int main()
{
char a[]="`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./";
int i,c;
while((c=getchar())!=EOF)
{
for(i=1;a[i] && a[i]!=c;i++);
if(a[i]) putchar(a[i-1]);
else   putchar(c);
}
}


5.1.2 TEX括号

输入:"Hello,World!"

输出:<Hello,World!>

#include <stdio.h>
int main()
{
int c,q=1;
while((c=getchar())!=EOF){
if(c=='"') {
printf("%c",q?'<':'>');
q=!q;
}else{
printf("%c",c);
}
}
}


5.1.3 周期串

输出一个周期串的最小周期

输入:HoHoHo

输出:2

#include <stdio.h>
#include <string.h>
int main()
{
int i,j;
char word[100];
scanf("%s",word);
int len=strlen(word);
for(i=1;i<len;i++)
if(len%i==0)
{
int ok=0;
for(j=i;j<len;j++){
if(word[j]!=word[j%i]) {
ok=1;
break;
}
}
if(ok==0){
printf("%d\n",i);
break;
}
}
return 0;
}


5.2.2 阶乘的精确值

输入:8

输出:40320

#include <stdio.h>
#include <string.h>
#define MAX 3000
int f[MAX];
int main()
{
int i,j,n;
memset(f,0,sizeof(f));
f[0]=1;
scanf("%d",&n);
for(i=2;i<=n;i++){
int c=0;
for(j=0;j<MAX;j++)
{
f[j]=f[j]*i+c;
c=f[j]/10;
f[j]%=10;
}
}
/*	int ok=0;
for(j=MAX-1;j>=0;j--)
{
if(ok){
printf("%d",f[j]);
}else if(f[j]){
printf("%d",f[j]);
ok=1;
}

}
*/
for(j=MAX-1;j>=0;j--) if(f[j]) break;//忽略前导零
for(i=j;i>=0;i--){
printf("%d",f[i]);
}
printf("\n");
return 0;
}



6174问题

时间限制:1000 ms | 内存限制:65535 KB

描述

假设你有一个各位数字互不相同的四位数,把所有的数字从大到小排序后得到a,从小到大后得到b,然后用a-b替换原来这个数,并且继续操作。例如,从1234出发,依次可以得到4321-1234=3087、8730-378=8352、8532-2358=6174,又回到了它自己!现在要你写一个程序来判断一个四位数经过多少次这样的操作能出现循环,并且求出操作的次数

比如输入1234执行顺序是1234->3087->8352->6174->6174,输出是4
输入第一行输入n,代表有n组测试数据。

接下来n行每行都写一个各位数字互不相同的四位数输出经过多少次上面描述的操作才能出现循环样例输入
1
1234

样例输出
4


#include <stdio.h>
#include <string.h>
#define MAX 1010
int buffer[MAX];
int get_next(int n)
{
char s[10];
sprintf(s,"%d",n);
int len=strlen(s);
int i=0,j=0;
for(i=0;i<len;i++)
{
int label=i;
for(j=i+1;j<len;j++)
if(s[label]>s[j]){
label=j;
}
int tmp=s[i];
s[i]=s[label];
s[label]=tmp;
}
int a,b;
sscanf(s,"%d",&a);
for(i=0;i<len/2;i++)
{
int tmp=s[i];
s[i]=s[len-i-1];
s[len-i-1]=tmp;
}
sscanf(s,"%d",&b);
return b-a;
}

int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%d",&buffer[0]);
printf("%d",buffer[0]);
int count=1;
for(;;)
{
buffer[count]=get_next(buffer[count-1]);
printf("-->%d",buffer[count]);
int ok=0;
for(int i=0;i<count;i++)
if(buffer[count]==buffer[i])
{
ok=1;
break;
}
if(ok){
break;
}
count++;
}
printf("\n%d\n",count);
}
printf("\n");
return 0;
}


小猴子下落

时间限制:3000 ms | 内存限制:65535 KB
难度:3

描述

有一颗二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从左到右从上到下的编号为1,2,3,·····,2的D次方减1。在结点1处放一个小猴子,它会往下跑。每个内结点上都有一个开关,初始全部关闭,当每次有小猴子跑到一个开关上时,它的状态都会改变,当到达一个内结点时,如果开关关闭,小猴子往左走,否则往右走,直到走到叶子结点。

一些小猴子从结点1处开始往下跑,最后一个小猴儿会跑到哪里呢?

输入输入二叉树叶子的深度D,和小猴子数目I,假设I不超过整棵树的叶子个数,D<=20.最终以 0 0 结尾输出输出第I个小猴子所在的叶子编号。样例输入
4 2  3 4  0 0

样例输出
12  7


第一种方法(不推荐,只要判断猴子第几次到达该位置,便可知猴子要去的位置。):
#include <stdio.h>
#include <string.h>
#define MAX 20
int arr[1<<MAX];
int main()
{
int D,I;
while(scanf("%d%d",&D,&I)!=EOF&&(D!=0&&I!=0))
{
memset(arr,0,sizeof(arr));
int i,k;
for(i=0;i<I;i++)
{
k=1;
for(;;)
{
int s=arr[k]?2*k+1:2*k;
arr[k]=!arr[k];
k=s;
if(k>((1<<D)-1)) break;
}
}
printf("%d ",k/2);
}
printf("\n");
return 0;
}



第二种方法:
#include <stdio.h>

int main()
{
int D,I,k;
while(scanf("%d%d",&D,&I)!=EOF&&(D!=0&&I!=0))
{
k=1;
for(int i=1;i<D;i++)
if(I%2==1)//判断该猴子到达某位置的奇偶性,便可知猴子要去的位置。
{
k=2*k;
I=(I+1)/2;
}else{
k=2*k+1;
I=I/2;
}
printf("%d ",k);
}
printf("\n");
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: