15年上机题

这篇博客包含了两个编程挑战:一是寻找相亲数,要求编写程序计算两个数的因子之和并判断是否为相亲数;二是模拟窗口点击,需要处理窗口层次和点击事件,以确定最终的窗口叠放顺序。

15年上机题

问题:相亲数
描述: 如果对于两个大于1的正整数x和y,x除了本身以外的因子之和等于y,y除了本身以外的因子之和等于x,则称x和y是一对相亲数。 比如220除了本身以外的因子之和110+55+44+22+20+11+10+5+4+2+1=284,而284除了本身以外的因子之和142+71+4+2+1=220,则220和284就是一对相亲数。 请你编写一个程序计算x和y分别除了本身以外的因子之和,并判断x和y是不是一对相亲数。x和y为大于1的int范围内的整数。
输入:x和y,空格隔开。
输出:第一行输出x,一个逗号,x的除了本身以外的因子之和的计算过程(见题意,要求降序输出每个因子),不要有多余的空格。 第二行输出y,一个逗号,y的除了本身以外的因子之和的计算过程(见题意,要求降序输出每个因子),不要有多余的空格。 第三行,如果x和y是一对相亲数输出1,否则输出0。文末换行可有可无。
样例:
标准输入
220 284
标准输出
220,110+55+44+22+20+11+10+5+4+2+1=284
84,142+71+4+2+1=220
1
标准输入
1184 1120
标准输出
1184,592+296+148+74+37+32+16+8+4+2+1=1210
1220,560+280+224+160+140+112+80+70+56+40+35+32+28+20+16+14+10+8+7+5+4+2+1=1904
0

#include <stdio.h>
#include <math.h>

int a[100];
int b[100];
int jx,jy;

int fx(int n){
    int sum=1;
    int k=int(sqrt(n));
    jx=0;
    for(int i=2;i<k;i++){
        if(n%i==0){
            sum+=i+n/i;
            a[jx++]=i;
            a[jx++]=n/i;
        }
    }
    if(sqrt(n)-k==0){
        sum+=k;
        a[jx++]=k;
    }
    return sum;
}

int fy(int n){
    int sum=1;
    int k=int(sqrt(n));
    jy=0;
    for(int i=2;i<k;i++){
        if(n%i==0){
            sum+=i+n/i;
            b[jy++]=i;
            b[jy++]=n/i;
        }
    }
    if(sqrt(n)-k==0){
        sum+=k;
        b[jy++]=k;
    }
    return sum;
}

void out(int x, int sumx, int kx, int ab[]){
    printf("%d,",x);
    if(kx%2==0){//除去1后其他因数个数为偶数
        for(int i=1;i<kx;i++,i++){
            printf("%d+",ab[i]);
        }
        for(int i=kx-2;i>=0;i--,i--){
            printf("%d+",ab[i]);
        }
        printf("1=%d\n",sumx);
    }
//    else{//除去1后其他因数个数为奇数
//        for(int i=1;i<kx;i++,i++){
//            printf("%d+",ab[i]);
//        }
//        for(int i=kx-1;i>=0;i--,i--){
//            printf("%d+",ab[i]);
//        }
//        printf("1=%d\n",x);
//    }
}

int main()
{
    int x,y;
    while(scanf("%d %d",&x,&y)!=EOF){
        int sumx=fx(x);
        int sumy=fy(y);
        //printf("sumx:%d sumy:%d\n",sumx,sumy);
        //printf("jx:%d jy:%d\n",jx,jy);
        out(x,sumx,jx,a);
        out(y,sumy,jy,b);

        if(sumx==y && x==sumy){
            printf("1\n");
        }else{
            printf("0\n");
        }
    }
    return 0;
}

优化如下:

#include <stdio.h>
#include <math.h>

int a[50],b[50],buf[50];//保存x,y的约数

//输出结果
void output(int *x,int *buf, int *size, int *sum){
    printf("%d,",*x);
    for(int i=*size-1;i>0;i--){
        printf("%d+",buf[i]);
    }
    printf("1=%d\n",*sum);
}

int main()
{
    int x,y,sumx,sumy;
    int sizea,sizeb;

    while(scanf("%d %d",&x,&y)!=EOF){
        sizea=sizeb=sumx=sumy=a[0]=b[0]=1;

        //计算x的约数,只用求出x^(1/2)内的约数即可
        int bound=(int)sqrt(x)+1;
        int i,len=0;
        for(i=2;i<bound;i++){
            if(x%i==0){
                a[sizea++]=i;
                buf[len++]=x/i;
                sumx+=i+x/i;
            }
        }
        for(i=len-1;i>=0;i--){
            a[sizea++]=buf[i];
        }

        //计算y的约数
        bound=(int)sqrt(y)+1;
        len=0;
        for(i=2;i<bound;i++){
            if(y%i==0){
                b[sizeb++]=i;
                buf[len++]=y/i;
                sumy+=i+y/i;
            }
        }
        for(i=len-1;i>=0;i--){
            b[sizeb++]=buf[i];
        }

        output(&x,a,&sizea,&sumx);
        output(&y,b,&sizeb,&sumy);
        if(sumx==y && sumy==x)printf("1\n");
        else printf("0\n");
    }
    return 0;
}

题目:窗口点击模拟
描述:
在计算机屏幕上,有N个窗口。窗口的边界上的点也属于该窗口。窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容。当你用鼠标点击某个点的时候,若其在窗口内,你就选择了处于被点击位置所属的最顶层窗口,并且这个窗口就会被移到所有窗口的顶层,而剩余的窗口的层次顺序不变,如果你点击的位置不属于任何窗口计算机就会忽略你这次点击。编写一个程序模拟点击窗口的过程:先从标准输入读入窗口的个数,窗口编号和位置(以窗口的左上角和右下角的坐标表示,先输入的窗口层次高),然后读入点击的次数和位置(以点击的坐标表示),编写程序求得经过上述点击后的窗口叠放次序。
假设:
1.屏幕左下角作为X轴和Y轴坐标原点,即坐标为(0,0),所有输入的坐标数值都是整数,并且都大于等于0,小于等于1000。
2.输出窗口的叠放次序时从最后点击后最顶层的窗口编号开始按层次依次输出;
3.输入的窗口个数大于0并且小于等于10,点击次数大于0并且小于等于20。

输入:
第一行窗口个数n,接下来n行每行一个窗口的编号、左下角坐标、右上角坐标。 接下来一行点击次数k,接下来k行每行一个点击坐标。
输出:
一行n个数字,表示K次点击后按层次排列的窗口编号,空格隔开。 行末空格与文末换行可有可无。

#include <stdio.h>

int a[10][5];
int b[20][2];

int main()
{
    int n;//窗口个数
    int k;//点击次数
    FILE *fp;
    fp=fopen("F:\\ToDo\\test1.txt","r");
    while(fscanf(fp,"%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            for(int j=0;j<5;j++){
                fscanf(fp,"%d",&a[i][j]);
            }
        }
        fscanf(fp,"%d",&k);
        for(int i=0;i<k;i++){
            for(int j=0;j<2;j++){
                fscanf(fp,"%d",&b[i][j]);
            }
        }

        int c[n+1]={0};
        for(int i=0;i<k;i++){
            for(int j=n-1;j>=0;j--){
                if(b[i][0]>=a[j][1] && b[i][0]<=a[j][3] \
                   && b[i][1]>=a[j][2] && b[i][1]<=a[j][4]){
                        c[a[j][0]]=i+1;//重复点击的窗口被覆盖
                        //printf("第%d次点击 %d号窗口\n",i+1,a[j][0]);
                        break;
                }
            }
        }

//        for(int i=1;i<n+1;i++){
//            printf("%d ",c[i]);
//        }
//        printf("\n\n");
        for(int i=k;i>=1;i--){
            for(int j=1;j<n+1;j++){
                if(c[j]==i){
                    printf("%d ",j);
                    //printf("第%d次点击 %d号窗口\n",i,j);
                    break;
                }
            }
        }
        for(int j=1;j<=n;j++){
            if(c[j]==0)printf("%d ",j);
        }
        printf("\n");
    }
}
//test1.txt
4
1 43 31 70 56
2 50 24 80 50
3 23 13 63 42
4 57 36 90 52
5
47 28
73 40
68 32
82 43
27 49
#include <stdio.h>

//窗口结构体,保存坐标及编号
struct window{
    int x1,y1,x2,y2;
    //<x1,y1>左下角坐标,<x2,y2>右上角坐标
    int num;//编号
}windows[11];

int order[11];//从顶向下保存窗口次序
int n,k;

//把数组中第i位元素插入到首位
void insert(int m){
    int tmp=order[m];
    for(int i=m;i>0;i--){
        order[i]=order[i-1];
    }
    order[0]=tmp;
}

//模拟点击,依次序判断是否属于某窗口
void click(int x,int y){
    int i;
    for(i=0;i<n;i++){
        int tmp=order[i];
        if(x>=windows[tmp].x1 && x<=windows[tmp].x2
           && y>=windows[tmp].y1 && y<=windows[tmp].y2){
            break;
        }
    }
    if(i==n)return;//点击非窗口区域
    else insert(i);//将点击到的窗口编号插入到order数组首位
}

int main()
{
    while(scanf("%d",&n)!=EOF && n!=0){
        int i;
        for(i=0;i<n;i++){
            scanf("%d%d%d%d%d",&windows[i].num,
            &windows[i].x1,&windows[i].y1,
            &windows[i].x2,&windows[i].y2);
            order[i]=i;//先输入的窗口层次高
        }
        scanf("%d",&k);
        while(k--){
            int x,y;
            scanf("%d%d",&x,&y);
            click(x,y);
        }

        //输出结果
        for(i=0;i<n;i++){
            printf("%d ",windows[order[i]].num);
        }
        printf("\n");
    }
    return 0;
}

题目:文章识别
描述:输入一篇可能未经排版的文章,挑选出其中的单词【单词中不包含“(”等特殊符号】,然后按字典序输出。
输入:从文件中读取文章
输出:按字典序输出单词

样例:
输入
When most kids go to school and study the knowledge, few special kids have made their history. A small boy from America wins the international contest by defeating adult competitors. He becomes the youngest winner. He has the gift and so many parents want to have such a kid. Though we are not that smart, we still can study hard to realize our dreams.
输出
a
adult
america
and
are
becomes
boy
by
can
competitors
contest
defeating
dreams
few
rom
gift
go
hard
has
have
he
history
international
kid
kids
knowledge
made
many
most
not
our
p
rents
realize
school
small
smart
so
special
still
study
such
that
the
their
though
to
want
we
when
winner
wins
youngest

/*
使用字符串数组保存单词
首先读出单词,利用二分查找把单词插入到单词表中
*/
#include <stdio.h>
#include <string.h>

char words[100][20];//单词表
int size;//已经找到的单词个数

//把单词插入到词典中
void insert(char *tmp,int p){
    if(size==0){
        strcpy(words[0],tmp);//将tmp复制到words[0]
    }else if(p<size){
        for(int i=size;i>p;i--){
            strcpy(words[i],words[i-1]);
            //将words[i-1]复制到words[i]
            //从后往前后移可避免覆盖
        }
    }
    strcpy(words[p],tmp);
    size++;
}

//采用二分查找的方式查找
void search(char *tmp,int left,int right){
    if(left>right){//未查找到则插入至单词表
        insert(tmp,left);//插入位置为left,将当前left及之后字符串后移
    }else{//二分查找定位插入位置,若找到则不插入
        int mid=(left+right)/2;

        //strcmp字符串比较,区分大小写
        int a=strcmp(tmp,words[mid]);//与中值比较
        if(a==0){
            return;//查找结果等于中值,不插入
        }else if(a<0){
            right=mid-1;//比中值小
        }else{
            left=mid+1;//比中值大
        }
        search(tmp,left,right);
    }
}

//输出单词表
void output(){
    for(int i=0;i<size;i++){
        printf("%s\n",words[i]);
    }
}

int main()
{
    FILE *fp=fopen("F:\\ToDo\\test2.txt","r");
    char tmp[20];
    size=0;

    int len=0;
    bool flag=false;//标记tmp字符串是否可以作为一个单词
    while(!feof(fp)){// feof()函数判断是否读到了文件结尾
        int c=fgetc(fp);
        //若读入的为空格等其他非字母字符则跳过,继续读入

        if((c>='a'&&c<='z') || (c>='A'&&c<='Z')){//读入连续字母会追加
            if(c>='A'&&c<='Z'){
                c=(c-'A')+'a';//将大写字母转换为小写
            }
            tmp[len++]=c;
            tmp[len]=0;//字符串末尾设置为'\0'
            flag=true;
        }else if(flag){//当if条件不满足才会执行,即读入字符为非字母才执行
            search(tmp,0,size-1);
            len=0;
            flag=false;
        }
    }
    fclose(fp);
    printf("%d\n",size);
    output();

    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值