OJ
求序列的第N项(改错)
问题描述
给定程序中函数fun的功能是:根据整型形参n,计算如下公式的值。

例如,若 n=10,则应输出:0.617977。
请改正程序中的语法错误,使它能得出正确的结果。
注意:不要改动 main 函数,不得增行或删行,也不得更改程序的结构!
#include <stdio.h>
/************found************/
int fun (int n) {
float A = 1;
int i;
/************found************/
for (i = 2; i < n; i++)
A = 1 / (1 + A);
return A ;
}
int main() {
int n ;
scanf("%d", &n);
printf("A%d=%f", n, fun(n));
return 0;
}
输入说明
输入一个正整数n
输出说明
根据源程序所给格式进行输出
输入范例
10
输出范例
A10=0.617977
代码
cpp
#include <stdio.h>
/************found************/
double fun (int n) {
float A = 1;
int i;
/************found************/
for (i = 2; i<=n; i++)
A = 1 / (1 + A);
return A ;
}
int main() {
int n ;
scanf("%d", &n);
printf("A%d=%f", n, fun(n));
return 0;
}
数组值对换(填空)
问题描述
将数组中的前半部分元素中的值和后半部分元素中的值对换。若数组中元素的个数n为奇数,则中间的元素不动。
例如:若a数组中的数据依次为:1、2、3、4、5、6、7、8、9,则调换后为:6、7、8、9、5、1、2、3、4。
请在程序的下划线处填入正确的内容并把下划线删除,使程序得出正确的结果。
注意:源程序存如下。
不得增行或删行,也不得更改程序的结构!
#include <stdio.h>
#define N 100
int main()
{
int n;
int a[N], i, t, p;
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
/**********found**********/
p = (n % 2 == 0) ? n / 2 : n / 2 + 1;
for (i = 0; i < n / 2; i++)
{
t = a[i];
/**********found**********/
a[i] = a[p + 2];
/**********found**********/
3 = t;
}
for (i = 0; i < n; i++)
printf("%4d ", a[i]);
return 0;
}
输入说明
首先输入一个正整数n,
然后输入n个正整数
输出说明
根据源程序所给格式进行输出
输入范例
9
1 2 3 4 5 6 7 8 9
输出范例
6 7 8 9 5 1 2 3 4
代码
cpp
#include <stdio.h>
#define N 100
int main()
{
int n;
int a[N], i, t, p;
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
/**********found**********/
p = (n % 2 == 0) ? n / 2 : n / 2 + 1;
for (i = 0; i < n / 2; i++)
{
t = a[i];
/**********found**********/
a[i] = a[p +i];
/**********found**********/
a[p+i]= t;
}
for (i = 0; i < n; i++)
printf("%4d ", a[i]);
return 0;
}
地铁门
问题描述
明明坐地铁久了,掌握了规律,发现地铁一般有8节车厢,每节车厢共有5个门,其中第1和第5个门靠近两端。
从第1节到第8节车厢,地铁门的编号从1到40。
此外,明明还发现,编号5的门和编号6的门靠近车厢连接处(即第1节和第2节车厢的连接部位),站在这种地方摇晃得更厉害,因此,他每次都避免从任何靠近车厢连接处的地方上车(除了编号5和6,还有别的门也靠近车厢连接处)。
注意,第1个门和第40个门是地铁两头的门,不靠近车厢连接处。
现在需要输入一个门的编号,你要告诉明明是否靠近车厢连接处,从而他能选择是否从该门上车。
输入说明
输入一个整数,表示门的编号
输出说明
如果门靠近车厢连接处,输出"Y"
如果不靠近车厢连接处,输出"N"
如果门的编号有误(不在1到40之间),输出"error"
所有输出不包括引号,也不包含空格。
输入范例
5
输出范例
Y
代码
cpp
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
if(n>=1&&n<=40)
{
if(n==1||n==40)
cout<<"N";
else if(n%5==0)
cout<<"Y";
else if(n%5==1)
cout<<"Y";
else
cout<<"N";
}
else
cout<<"error";
return 0;
}
暗恋
问题描述
同在一个高中,他却不敢去找她,虽然在别人看来,那是再简单不过的事。暗恋,是他唯一能做的事。他只能在每天课间操的时候,望望她的位置,看看她倾心的动作,就够了。操场上的彩砖啊,你们的位置,就是他们能够站立的地方,他俩的关系就像砖与砖之间一样固定,无法动摇。还记得当初铺砖的工人,将整个操场按正方形铺砖(整个操场可视为R行C列的矩阵,矩阵的每个元素为一块正方形砖块),正方形砖块有两种,一种为蓝色,另一种为红色。我们定义他和她之间的"爱情指标"为最大纯色正方形的面积,请你写一个程序求出"爱情指标"。
输入说明
第一行两个正整数R和C,R和C都不超过200。
接下来R行C列描述整个操场,红色砖块用1来表示,蓝色砖块用0来表示。
输出说明
一个数,表示他和她之间的"爱情指标"。
输入范例
5 8
0 0 0 1 1 1 0 1
1 1 0 1 1 1 1 1
0 1 1 1 1 1 0 1
1 0 1 1 1 1 1 0
1 1 1 0 1 1 0 1
输出范例
9
代码
cpp
#include<bits/stdc++.h>
using namespace std;
#define MAX 1005
int p[MAX][MAX];
//以(a,b)为左上角,ans为边长的正方形是否为纯色
int check(int a,int b,int ans){
int temp=p[a][b];
for(int i=0;i<ans;i++)
for(int j=0;j<ans;j++){
if(p[a+i][b+j]!=temp)return 0;
}
return 1;
}
int main(void){
int R,C;
cin>>R>>C;
int mmax=R>C?R:C;//
int ans=0;
for(int i=0;i<R;i++)
for(int j=0;j<C;j++)
cin>>p[i][j];
for(int i=0;i<R;i++)
for(int j=0;j<C;j++)
for(int k=ans+1;k<=mmax;k++){
if(i+k<=R&&j+k<=C)
if(check(i,j,k))
ans=k;
else break;
}
cout<<ans*ans;
return 0;
}
多级排序
问题描述
本学期大家学习了C语言程序设计,现在需要你实现一个成绩排名系统。
假设他们每个人都有三门课程,C语言程序设计、计算机导论和英语,要求把成绩好的同学放到前面。
具体要求是先按个人的总成绩进行排名,如果某两个人的总分相同,则按他们的C语言程序设计成绩进行排名,如果总成绩和C语言程序设计成绩都相同时,则再按照他们的计算机导论成绩进行排名(输入的数据保证这两个人的计算机导论成绩不会再相同)。try to do it ^_^!
输入说明
输入多组数据。
每组数据的第一行为学生的数目N(N<=100),接下来的N行,每行输入一个学生的信息,包括:学生姓名(长度小于20)、C语言程序设计成绩(0到100的整数)、计算机导论成绩(0到100的整数)和英语成绩(0到100的整数)。
每两个数据之间有一个空格,学生姓名中不包含空格。
输出说明
对于每组输入,输出按照成绩从高到低排序的姓名、总分、C语言程序设计、计算机导论和英语成绩序列,每个学生占一行。
我们保证不会存在两个人总成绩和各门的成绩都分别相同的情况。
两组输出数据之间有一个空行,第一组数据前面及最后一组数据后面无空行。
输入范例
3
Henry 98 95 90
Marry 90 88 89
Jhon 92 90 95
3
zhangsan 90 90 90
lisi 85 95 90
wangwu 85 90 95
输出范例
Henry 283 98 95 90
Jhon 277 92 90 95
Marry 267 90 88 89
zhangsan 270 90 90 90
lisi 270 85 95 90
wangwu 270 85 90 95
代码
cpp
#include<bits/stdc++.h>
using namespace std;
struct Student{
string name;
int C_score;
int computer_score;
int english;
int sum;
};
bool cmp(Student a,Student b)
{
if(a.sum!=b.sum)
return a.sum>b.sum;
else
{
if(a.C_score!=b.C_score)
return a.C_score>b.C_score;
else
{
if(a.computer_score!=b.computer_score)
return a.computer_score>b.computer_score;
}
}
}
int main()
{
int N;
bool first=true;
while(cin>>N)
{
Student stu[N];
for(int i=0;i<N;i++)
{
cin>>stu[i].name>>stu[i].C_score>>stu[i].computer_score>>stu[i].english;
}
for(int i=0;i<N;i++)
{
stu[i].sum=stu[i].computer_score+stu[i].C_score+stu[i].english;
}
sort(stu,stu+N,cmp);
if(!first)
cout<<endl;
first=false;
for(int i=0;i<N;i++)
{
cout<<stu[i].name<<" "<<
stu[i].sum<<" "<<stu[i].C_score<<" "
<<stu[i].computer_score<<" "
<<stu[i].english<<endl;
}
}
return 0;
}
木棍还原
问题描述
小明有一些相同长度的木棍,他将它们随机切割,直到所有切割后的短棍长度不超过50。现在他想把棍子恢复到原来的状态,但他忘了他原来有多少根棍子(但知道至少有两根),也不知道它们原来有多长。请帮助他,设计一个程序,计算出这些棍子的最小原始长度。
输入说明
输入包含多组数据,每组数据包含2行。
第一行包含切割后的短棍的数量n,n<=64。
第二行包含这些短棍的长度,由空格分隔。所有长度值都是大于0的整数。
最后一组数据之后是一个0,表示输入结束。
输出说明
为每组数据输出一行,包括一个整数,表示棍子原始的长度。
如果原始长度有多种可能,则输出最小的那个。
输入范例
7
2 7 7 7 7 10 20
6
1 2 3 11 11 20
0
输出范例
30
24
代码
错误版:
cpp
#include<bits/stdc++.h>
using namespace std;
//木棍长度相同
int main()
{
int n;
while(cin>>n)
{
if(n==0)
return 0;
int len[n];
for(int i=0;i<n;i++)
cin>>len[i];
int sum=0;
for(int i=0;i<n;i++)
{
sum+=len[i];
}
int temp[n];
for(int i=0;i<n;i++)
{
temp[i]=len[i];
}
sort(temp,temp+n);
int x=temp[n-1];
int min=-1;
for(int i=2;;i++)
{
if(sum%i==0&&sum/i>=x)
{
if(min<sum/i)
min=sum/i;
break;
}
}
cout<<min<<endl;
}
return 0;
}
深度优先搜索:
cpp
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> a;
bool used[70];
// 当前正在拼一根长度为 len 的木棍,已经拼了 now,已经拼好 cnt 根
bool dfs(int len, int now, int cnt) {
// 全部拼完
if (cnt == n) return true;
for (int i = 0; i < n; i++) {
if (used[i]) continue;
// 加上这根不超过长度
if (now + a[i] <= len) {
used[i] = true;
// 刚好拼完一根,开始拼下一根
if (now + a[i] == len) {
if (dfs(len, 0, cnt + 1))
return true;
} else {
// 继续拼当前这根
if (dfs(len, now + a[i], cnt + 1))
return true;
}
used[i] = false;
}
}
return false;
}
int main() {
while (cin >> n && n != 0) {
a.resize(n);
int sum = 0, maxLen = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
sum += a[i];
maxLen = max(maxLen, a[i]);
}
// 从小到大试每一个可能的原始长度
int ans = 0;
for (int len = maxLen; len <= sum / 2; len++) {
if (sum % len != 0) continue; // 必须能整除
memset(used, 0, sizeof(used));
if (dfs(len, 0, 0)) {
ans = len;
break;
}
}
cout << ans << endl;
}
return 0;
}
天天向上
问题描述
A同学的学习成绩十分不稳定,于是老师对他说:"只要你连续4天成绩有进步,那我就奖励给你一朵小红花。"可是这对于A同学太困难了。于是,老师对他放宽了要求:"只要你有4天成绩是递增的,我就奖励你一朵小红花。"即只要对于第i、j、k、l四天,满足i<j<k<l并且对于成绩wi<wj<wk<wl,那么就可以得到一朵小红花的奖励。现让你求出,A同学可以得到多少朵小红花。
输入说明
第一行一个整数n,表示总共有n天。第二行n个数,表示每天的成绩wi。
n<=1000,0<=wi<=109。
输出说明
一个整数,表示总共可以得到多少朵小红花。
输入范例
6
1 3 2 3 4 5
输出范例
6
个人总结
找到长度为4的所有递增子序列
dp1[i] = 以 w[i] 结尾的长度为 1 的递增子序列的数量(其实就是 1)。
dp2[i] = 以 w[i] 结尾的长度为 2 的递增子序列的数量。
dp3[i] = 以 w[i] 结尾的长度为 3 的递增子序列的数量。
dp4[i] = 以 w[i] 结尾的长度为 4 的递增子序列的数量。
代码
cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> w(n + 1); // 成绩数组,从1开始索引
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
// dp1[i]: 以第i天结尾的长度为1的递增子序列个数(恒为1)
// dp2[i]: 以第i天结尾的长度为2的递增子序列个数
// dp3[i]: 以第i天结尾的长度为3的递增子序列个数
// dp4[i]: 以第i天结尾的长度为4的递增子序列个数
vector<long long> dp1(n + 1, 0);
vector<long long> dp2(n + 1, 0);
vector<long long> dp3(n + 1, 0);
vector<long long> dp4(n + 1, 0);
for (int i = 1; i <= n; i++) {
dp1[i] = 1; // 每个元素自身构成长度为1的递增子序列
for (int j = 1; j < i; j++) {
if (w[j] < w[i]) {
// 所有以j结尾的长度为1的子序列,加上w[i]后变为长度为2
dp2[i] += dp1[j];
// 所有以j结尾的长度为2的子序列,加上w[i]后变为长度为3
dp3[i] += dp2[j];
// 所有以j结尾的长度为3的子序列,加上w[i]后变为长度为4
dp4[i] += dp3[j];
}
}
}
// 统计所有长度为4的递增子序列
long long total = 0;
for (int i = 1; i <= n; i++) {
total += dp4[i];
}
cout << total << endl;
return 0;
}
英语
