湘潭大学2018年上学期程序设计实践模拟考试1参考题解

这个博客不再更新,新博客地址请戳

总体难度较程设考试题而言,偏简单,考试的签到题会难一点,难题也会难一点。
OJ需要用校园网才能进去。


A 三个数 http://172.22.112.249/exam/index.php/problem/exam_read/id/1384/exam_id/160

思路:
不难想到,如果要让式子等于0,那么式子中一定要有一个减号。
有a+b-c=0 a*b-c=0两种形式。
签到题一般会比这个难。

参考代码:

#include 
using namespace std;

int main(){
    int t;cin>>t;
    while(t--){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        int ok=0;

        if(a+b==c)ok=1;
        if(a+c==b)ok=1;
        if(b+c==a)ok=1;

        if(a==c*b)ok=1;
        if(a==b*c)ok=1;
        if(b==a*c)ok=1;

        if(a*b==c)ok=1;
        if(a*c==b)ok=1;
        if(b*c==a)ok=1;

        if(b==c*a)ok=1;
        if(c==b*a)ok=1;
        if(c==a*b)ok=1;

        if(ok)puts("Yes");
        else puts("No");
    }
    return 0;
}

B 奇怪的数字 http://172.22.112.249/exam/index.php/problem/exam_read/id/1385/exam_id/160

思路:
题目说了从n中抽出1位作为x,剩余组成y。
那么我们枚举从1到9枚举x,从1到1e6枚举y,得到n=x*y。
然后把n拆分计数,再把x和y分别拆分计数,如果数码完全相同就压入set。

参考代码:

#include 
using namespace std;
typedef long long ll;

bool check(int i,int j,int n){
    int vis[10]={0};
    while(n){
        int a=n%10;
        n/=10;
        vis[a]++;
    }
    while(i){
        int a=i%10;
        i/=10;
        vis[a]--;
    }
    while(j){
        int a=j%10;
        j/=10;
        vis[a]--;
    }
    for(int i=0;i<10;i++)if(vis[i]!=0)return 0;
    return 1;
}

set vec;

int main(){
    for(ll  i=0;i<10;i++){
        for(ll j=i+1;j<=1e6;j++){
            ll n=i*j;
            if(n>1e6)break;
            if(check(i,j,n)){
                vec.insert(n);
            }
        }
    }
    for(set::iterator it=vec.begin();it!=vec.end();it++){
        cout<<*it<

C 字符矩阵 http://172.22.112.249/exam/index.php/problem/exam_read/id/1386/exam_id/160

思路:
官方题解是曼哈顿距离。
感觉是C语言考试既视感啊。
我的做法是找规律:
输入c,int a = c-‘A’+1;
那么前面a行分为一类,后面a-1行是前面反过来的。
对于每一行,可以拆成4部分,
分别是递增,递减,递增,递减的。(详见代码)
于是可以直接搞出来。

参考代码:

#include 
using namespace std;

int main(){
    char c;
    while(cin>>c&&c!='#'){
        for(int i=0;i<=c-'A';i++){
            for(char st=c-i;st<=c;st++){
                printf("%c",(char)(st));
            }
            for(char st=c-1;st>='A'+i;st--){
                printf("%c",(char)(st));
            }
            for(char st='A'+i+1;st<=c;st++){
                printf("%c",(char)(st));
            }
            for(char st=c-1;st>=c-i;st--){
                printf("%c",(char)(st));
            }
            puts("");
        }
        for(int i=c-'A'-1;i>=0;i--){
            for(char st=c-i;st<=c;st++){
                printf("%c",(char)(st));
            }
            for(char st=c-1;st>='A'+i;st--){
                printf("%c",(char)(st));
            }
            for(char st='A'+i+1;st<=c;st++){
                printf("%c",(char)(st));
            }
            for(char st=c-1;st>=c-i;st--){
                printf("%c",(char)(st));
            }
            puts("");
        }
    }
    return 0;
}

D Game http://172.22.112.249/exam/index.php/problem/exam_read/id/1387/exam_id/160

思路:
这题完全照着题意写就行了。
维护一下比分;
记录一下开始标志;
记录是谁的回合;
判断是否猜中;
最后输出比分便可。

参考代码:

#include 
using namespace std;

int main(){
    int val;
    char s[10][10];
    int now=1;
    int cnt=1;
    int cnta=0,cntb=0;
    int beg=1;
    while(scanf("%d%s%s%s%s",&val,s[1],s[2],s[3],s[4])!=EOF){
        int val2 = 0;
        if(s[1][0]=='P')val2+=5;
        if(s[2][0]=='P')val2+=5;
        if(s[3][0]=='P')val2+=5;
        if(s[4][0]=='P')val2+=5;

        if(beg==1){
            beg=0;
            if(now==1){
                printf("Alice start game %d\n",cnt);
            } else printf("Bob start game %d\n",cnt);
        }

        if(val==val2){
            beg=1;
            if(now==1){
                printf("Alice win game %d\n",cnt++);cnta++;
            } else {
                printf("Bob win game %d\n",cnt++);cntb++;
            }
        }
        else {
            beg=0;
            if(now==1){
                puts("Change to Bob");now=2;
            } else {
                puts("Change to Alice");now=1;
            }
        }
    }
    printf("Game over %d:%d\n",cnta,cntb);
    return 0;
}

E Longest Peak Sequence http://172.22.112.249/exam/index.php/problem/exam_read/id/1388/exam_id/160

思路:
简单的动态规划。
我们可以把LPM拆分成两部分,一部分是上升子序列,一部分是下降子序列。

pre[j]表示到序列的第j个为止,能够得到的最长上升子序列,一开始置0。
那么 如果有a[i]>a[j] && i>j ,那么pre[i] = max(pre[i] , pre[j] + 1);

suf[j]表示到序列的第j个为止,能够得到的最长下降子序列,一开始置0。
同上。

然后我们遍历所有元素,如果第i个位置的左边有比他小的,右边有比他大的,那么更新答案。

参考代码:

#include 
using namespace std;

int main(){
    int a[10005];
    int pre[1005];
    int suf[1005];
    int t;cin>>t;
    while(t--){
        memset(pre,0,sizeof pre);
        memset(suf,0,sizeof suf);
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            for(int j=1;ja[j])
                    pre[i]=max(pre[i],pre[j]+1);
            }
        }
        for(int i=n;i>=1;i--){
            for(int j=n;j>i;j--){
                if(a[i]>a[j]){
                    suf[i]=max(suf[i],suf[j]+1);
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            if(pre[i]&&suf[i]){
                ans=max(ans,pre[i]+suf[i]+1);
            }
        }
        cout<

F Black White Chess http://172.22.112.249/exam/index.php/problem/exam_read/id/1389/exam_id/160

思路:
这题是2018CCPC湘潭邀请赛热身赛的原题,当时岑巨写的,自己不会,气气!
然后在MLE+TLE的压力下,染了个色,过了,写的贼丑。
(当时想的太乱了,考完还被谢大说写的搓,气气*2!)

对于一个44的棋盘,黑白翻转,那么我们可以把44的棋盘压缩成一个32位的数字。
一共有pow(2,16)种棋盘,对于每种棋盘,有4+4+9种翻转方式。
我们可以预处理出所有棋盘对于所有翻转方式能够得到的棋盘,并把它们染成同一种颜色。

预处理完毕后,直接进行O(1)的输入输出。

如果两个棋盘的颜色相同,输出yes,否则输出no。

参考代码(写搓了不好意思qwq):

#include 
using namespace std;
int ok;
set st[2000];
int cnt=1;
int vis[1<<16+10];
int change(int val,int q,int w,int e,int r){
    val^=(1<

仅供参考。
转载请注明出处蟹蟹!

你可能感兴趣的:(XTU—程序设计实践网站)