第七周程序设计课解题报告

第七周程序设计课解题报告
1.different triangs
题目大意:给出n条边,任取其中三条,问有多少种情况取出的三条边能组成三角形。
解:先使用数组把边长存起来,然后用三重循环去枚举取边方案,再用if语句判断取出的三条边是否能组成三角形(我使用了函数实现这个功能) 
代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>


using namespace std;


bool check(int a, int b, int c){
    if ((a+b>c)&&(a+c>b)&&(b+c>a)) return true;
    return false;
}


int main(){
    int n, cas, a[1111];
    cin>>cas;
    while (cas--){
        cin>>n;
        for (int i=1; i<=n; i++) cin >> a[i];
        int ans=0;
        for (int i=1; i<=n-2; i++)
            for (int j=i+1; j<=n-1; j++)
                for (int k=j+1; k<=n; k++)
                    if (check(a[i], a[j], a[k])) ans++;


        cout << ans << endl;
    }
    return 0;
}                                 








2.矩形边框
题目大意:给出矩形的宽度和高度,输出由*号围成的矩形边框.
解:很容易发现,其实除了行数为1,h,列数为1,w的方格应该是*号外,其他都是空格,所以用if处理输出即可。
代码:
// Problem#: 12074
// Submission#: 3157183
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>


using namespace std;


int main(){
    int n, cas, m;
    cin>>cas;
    while (cas--){
        cin>>m>>n;
        for (int i=1; i<=n; i++){
            for (int j=1; j<=m; j++){
                if (i==1 || i==n || j==1 || j==m) cout <<'*';
                else cout <<' ';
            }
            cout << endl;
        }
        cout << endl;
    }
    return 0;
}                                 




3.分解质因数
题目大意:把每个输入的数进行质因数拆分
解:暴力拆分也不会超时,不过其实枚举质因数的时候枚举到根号n就可以退出了(但是这样做记得要枚举自己因为自己可能是一个质数)
代码:(这题因为读错题少行末没有输出空格PE了一次囧)
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>


using namespace std;


int main(){
    int n;
    cin>>n;
    while (n--){
        int now;
        cin>>now; int sum=0, i=2;
        while (now>1){
            while (now%i==0){
                sum++;




                cout << i;
                cout <<' ';
                now/=i;
            }
            i++;
        }
        cout << endl;
    }
    return 0;
}                                 








4.ELLIPSE
题目大意:给出一个椭圆,问有多少个整点(比如x,y是整点的充要条件是x,y都是整数)严格在椭圆内部(椭圆上的点不算)
 解:相信判断点是否在椭圆内的公式大家都会吧,所以暴力枚举整数点就可以了,但是如果枚举题目范围内所有的点感觉太暴力不知道会不会跪(这是我当时的想法,现在算一算貌似不会跪>W<),我就加了一个小优化。给出焦点和长半轴长d后,可知整点一定不会小于左焦点横坐标减d(最坏情况,哪怕焦点重合,若整点坐标小于左焦点横坐标减d,整点到两焦点距离必然大于d),同理可以算出其他边界。我继续使用函数求距离因为看起来会舒服一些。没学过的同学可以试着模仿一下,相信你会喜欢这种风格的。
哦对了,我求最大最小值没有用algorithm库里的max和min函数,而是我自己用define定义了这样的写法,有兴趣学习的同学可以搜索一下define的用途以及三元运算符“ a?b:c”
擦再看一眼貌似struct大家不知道用过没= =,不会的就问我,不要打我(抱头) 
代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>


#define SQR(x) ((x)*(x))
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)


using namespace std;


struct point{double x, y;};


double dist(point a, point b){
    return sqrt(SQR(a.x-b.x)+SQR(a.y-b.y));
}


int main(){
    int n, cas, m;
    cin>>cas;
    while (cas--){
        point f1, f2;
        int d;
        cin>>f1.x>>f1.y>>f2.x>>f2.y>>d;
        int x1, x2, y1, y2;
        x1=MIN(f1.x, f2.x); x2=MAX(f1.x, f2.x);
        y1=MIN(f1.y, f2.y); y2=MAX(f1.y, f2.y);
        x1-=d; x2+=d;
        y1-=d; y2+=d;
        int ans=0;
        for (int x=x1; x<=x2; x++)
            for (int y=y1; y<=y2; y++){
                point tmp; tmp.x=x; tmp.y=y;
                if ((dist(f1, tmp)+dist(f2, tmp))<d) ans++;
        }
        cout << ans << endl;
    }
    return 0;
}                                  




5.Prime Palindromes
题目大意:求区间[a,b]内的回文数素数
为什么要出这道题!!!!!
解:吭,跑题了。这道题感觉大家第一时间会倾向于暴力枚举,但参见我上一篇文章,算复杂度的事情,因为这里b可以去到1亿的,出数据的人和(丧)蔼(心)可(病)亲(狂)一点出几个[5,100000000]的数据程序就tle了,所以我们不能这样暴力做。
那么如何优化呢?其实我们可以利用回文数的性质很好地吧复杂度优化下来。因为为啥不用枚举全部的数呢?因为我们需要的仅仅是回文数,而回文数知道了左半边即可知道右半边了。对了,我们枚举左半边的数就好了,哪怕是九位数,我们也只需要枚举1~99999即可,如此我们便将复杂度从O(n)变成了O(根号n)。把回文数求出来了便求一下是否素数就好(相信大家都会,而且我依旧是用函数实现)
PS:
当然此题存在很多细节讨论,比如我枚举生产后发现答案不是单调递增的,所以我先把答案保存然后排序输出。因为考虑到大家没有学到数组,我就没有用拆位放入数组翻转的方法实现还原回文数,而是直接用数学方法(最后还是用到了数组TAT,但是你们相信我这题理论上我的方法还是不要用到数组的,跟别的组长比起来用什么dfs还有打表这种高科技我自认为我还是很有节操的(⊙o⊙)。想学习高科技的同学可以搜索 递归,打表的话私聊问吧,因为我觉得只算技巧而不是什么数据结构啊算法这方面的东西)  而翻转回文数的时候要用到10的n次方幂,因此我没有每一次都pow一下而是先预处理把要用到的次方幂保存。
PS2:我的注释语句是我调试用的,想了一下没有删掉,在最后附一个删注释版。不会调试的可以参考下,另外sort的函数可以接触一下,理解原理不太容易但是会用还是挺简单的)


代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>


#define SQR(x) ((x)*(x))
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)


using namespace std;


struct point{double x, y;};


bool check(int x){
    for (int i=2; i<=trunc(sqrt(x)); i++)
    if (x%i==0) return false;
    return true;
}
int aa[1000000];
long long poww[13];


int main(){
    poww[0]=1;
    for (int i=1; i<=12; i++) poww[i]=poww[i-1]*10;
    long long a, b, now, tot;
    while (cin>>a>>b && a+b>0){
        tot=0;
        for (int lab=1; lab<=9; lab++){
            if (poww[lab-1]>b) break;
           // cout <<'!' << lab << endl;
            int lim=poww[(lab+1)/2]-1;
           // cout << lim << endl;
            for (int i=1; i<=lim; i++)if (i%2==1){
                now=i;
               // cout << i << endl;
                for (int j=1; j<=lab; j++){
                    if (lab-j+1 == j) break;
                    long long tt=(i/poww[j-1]);
                  //  cout << tt << endl;
                    now+=(poww[lab-j])*(tt%10);
                }
               // cout << i <<' '<< now << endl;
                if ((now>=a)&&(now<=b)&&(check(now))) {
                    aa[++tot]=now;
                }


            }


        }
        sort(aa+1, aa+1+tot);
        for (int i=1; i<=tot; i++)
            if (aa[i]>1) printf("%d\n", aa[i]);
    }
    return 0;
}                  




无注释版:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>


#define SQR(x) ((x)*(x))
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)


using namespace std;


struct point{double x, y;};


bool check(int x){
    for (int i=2; i<=trunc(sqrt(x)); i++)
    if (x%i==0) return false;
    return true;
}
int aa[1000000];
long long poww[13];


int main(){
    poww[0]=1;
    for (int i=1; i<=12; i++) poww[i]=poww[i-1]*10;
    long long a, b, now, tot;
    while (cin>>a>>b && a+b>0){
        tot=0;
        for (int lab=1; lab<=9; lab++){
            if (poww[lab-1]>b) break;
            int lim=poww[(lab+1)/2]-1;
            for (int i=1; i<=lim; i++)if (i%2==1){
                now=i;
                for (int j=1; j<=lab; j++){
                    if (lab-j+1 == j) break;
                    long long tt=(i/poww[j-1]);
                    now+=(poww[lab-j])*(tt%10);
                }
                if ((now>=a)&&(now<=b)&&(check(now))) {
                    aa[++tot]=now;
                }


            }


        }
        sort(aa+1, aa+1+tot);
        for (int i=1; i<=tot; i++)
            if (aa[i]>1) printf("%d\n", aa[i]);
    }
    return 0;
}                                              
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值