第七周程序设计课解题报告
2015-04-12 22:51
190 查看
第七周程序设计课解题报告
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;
}
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;
}
相关文章推荐
- 解题报告:N.密码破解 (数论 含推导) “盛大游戏杯”第15届上海大学程序设计联赛夏季赛
- 团体程序设计天梯赛-练习集 L2-009. 抢红包 解题报告
- 2014年山东省第五届ACM大学生程序设计竞赛解题报告
- 第十二周程序设计课解题报告
- 华中农业大学第五届程序设计大赛网络同步赛解题报告(转)
- 第四届吉林省大学生程序设计大赛个人解题报告 Problem H: New Feature in Windows 7
- 2016 大学生程序设计竞赛亚洲区域赛青岛赛区(ICPC)解题报告
- 2013年4月_武科大程序设计大赛(复赛-非专业组)_解题报告(problem 1005)
- 团体程序设计天梯赛-练习集 L2-010. 排座位 解题报告
- 团体程序设计天梯赛-练习集 L3-008. 喊山 bfs 解题报告
- 第十五周程序设计作业解题报告
- 河南省第七届ACM大学生程序设计竞赛 解题报告
- 华中农业大学第五届程序设计大赛网络同步赛解题报告2(转)
- C++程序设计实验报告(四十八)---第七周任务一
- 2008湘潭大学程序设计比赛解题报告
- ECNU第四届程序设计竞赛解题报告
- 浙江省第8届程序设计竞赛解题报告
- 2013年4月_武科大程序设计大赛(复赛-非专业组)_解题报告(problem 1006)
- UESTC-第五届ACM趣味程序设计竞赛第四场(正式赛)--不完全解题报告
- 团体程序设计天梯赛-练习集 L2-011. 玩转二叉树 解题报告