文章目录
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1061
解题思路1:
1.设置3个数组manfen,biaoda,xueda
2.先输入进去manfen,biaoda
3.双层for循环,输入学生答案,与biaoda对比,如果一样则sum累加manfen,循环完后输出
参考代码:
#include<iostream>
#include<set>
using namespace std;
/*
解题思路:
*/
int main()
{
int n,m;
cin >> n >> m;
int manfen[m],biaoda[m],xueda[m];
for(int i=0; i<m; i++)
cin >> manfen[i];
for(int i=0; i<m; i++)
cin >> biaoda[i];
for(int i=0; i<n; i++)
{
int sum=0;
for(int j=0; j<m; j++)
{
int temp;
cin >> temp;
if(temp==biaoda[j])
sum+=manfen[j];
}
cout << sum << endl;
}
return 0;
}
1062
解题思路1:
1.先找M1,M2的最小公倍数S1,然后在找S1与K的最小公倍数K1
2.通分,将N1变为L1,将N2变为L2
3.找L1~L2之间找K1/K的倍数
4.写一个将分数化为最简分数的函数huajian,对于上面所有找的值进行化简,判断其分母是否为K,是则输出;不是
则不输出
参考代码1:
#include<iostream>
#include<cstdio>
using namespace std;
/*
解题思路:
*/
int zuiyin(int a,int b)
{
int max=-1;
if(a>b && a%b==0)
return b;
else if(a<b && b%a==0)
return a;
int temp=a>b?b:a;
for(int i=1; i<temp; i++)
{
if(a%i==0 && b%i==0)
if(i>max)
max=i;
}
return max;
}
int main()
{
int N1,N2,M1,M2,L1,L2,K;
scanf("%d/%d %d/%d %d",&N1,&M1,&N2,&M2,&K);
int S1=M1*M2/zuiyin(M1,M2);
int K1=K*S1/zuiyin(S1,K);
L1=K1/M1*N1;
L2=K1/M2*N2;
int flag=0;
for(int i=L1+1; i<L2; i++)
if(i%(K1/K)==0)
if(zuiyin(i,K1)==K1/K)
{
if(flag!=0)
cout << " ";
printf("%d/%d",i/(K1/K),K);
flag++;
}
return 0;
}
解题思路2:
1.不用找M1,M2,K的最大公约数。
2.用分母相乘的方法,先找到 num/K 比N1/M1大的最小num
3.用while循环,也是用分母相乘的方法,找到所有num/k 小于 N2/M2,同时判断num与k之间的最大公约数是否为1 是就输出
4.详见如下图
参考代码2:
#include<iostream>
using namespace std;
int gcd(int a, int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int n1,m1,n2,m2,k;
scanf("%d/%d %d/%d %d",&n1,&m1,&n2,&m2,&k);
if(n1*m2>m1*n2)
{
swap(n1,n2);
swap(m1,m2);
}
int num=1;
while(n1*k>=m1*num)
num++;
int flag=0;
while(num*m2<k*n2)
{
if(gcd(num,k)==1)
{
if(flag!=0)
cout << " ";
printf("%d/%d",num,k);
flag++;
}
num++;
}
return 0;
}
知识总结:
1.求最大公约数—辗转相除法
int gcd(int a, int b)
{
return b==0?a:gcd(b,a%b);
}
1063
参考代码:
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int main()
{
double max=-1.0,temp,temp1,temp2;
int n;
cin >> n;
for(int i=0; i<n; i++)
{
cin >> temp1 >> temp2;
temp=sqrt(temp1*temp1+temp2*temp2);
if(temp>max)
max=temp;
}
printf("%.2f",max);
return 0;
}
1064
解题思路:
1.对于每一个输入的数字,求其每个位上的数字和
2.将其insert入set类型a中
参考代码:
#include<iostream>
#include<set>
using namespace std;
/*
解题思路:
*/
int main()
{
int n;
cin >> n;
int flag=0;
set<int>a;
set<int>::iterator ita;
for(int i=0; i<n; i++)
{
int temp;
cin >> temp;
int num=0;
while(temp!=0)
{
num+=temp%10;
temp/=10;
}
a.insert(num);
}
cout << a.size() << endl;
for(ita=a.begin(); ita!=a.end(); ita++)
{
if(flag!=0)
cout << " ";
cout << *ita;
flag++;
}
return 0;
}
知识总结:
1.用set类型来存储值,一方面数字是按升序排列,另一方面在存储时是没有重复的插入
1065
解题思路1:
1.设置一个couple数组来存放夫妻ID,下标为a中存放b;下标为b中存放a
2.设置guest来存放参加晚会的ID,如果参见晚会的人有对象,则在isExist数组中存放参见晚会的人的对象值为1表示参加晚会的人的对象的对象来参加晚会了,如下图所示
3.要删除isExist中值为1的元素,保存值为0的元素
4.最后按要求输出
参考代码1:
#include <iostream>
#include <vector>
#include <set>
using namespace std;
/*
解题思路:
*/
int main()
{
int n, a, b, m;
cin >> n;
vector<int> couple(100000, -1); //设置一个长度为100000,初值为-1的数组couple , 设置数组长度为100000是因为数组下标是00000~99999
for (int i = 0; i < n; i++) //将配对的数字,一个做下标,一个做元素值
{
scanf("%d%d", &a, &b);
couple[a] = b;
couple[b] = a;
}
cin >> m;
vector<int> guest(m), isExist(100000); //isExist也是数组长度为100000,因为下标也是从00000~99999
for (int i = 0; i < m; i++) //将所有输入的客人的配偶做下标,值设为1
{
cin >> guest[i];
if (couple[guest[i]] != -1)
isExist[couple[guest[i]]] = 1;
}
set<int> s;
for (int i = 0; i < m; i++) //主要删除此人及配偶
{
if (!isExist[guest[i]])
s.insert(guest[i]);
}
printf("%d\n", s.size());
for (auto it = s.begin(); it != s.end(); it++)
{
if (it != s.begin())
printf(" ");
printf("%05d", *it);
}
return 0;
}
解题思路2:
1.设置一个2列,n行的一个二维数组来存储夫妻对数
2.b来存放参加晚会的人
3.xunzhao函数表示如果此人有对象则返回其对象的下标,如果此人没对象则返回100000
4.循环b结合xunzhao函数,如果参加晚会的人有对象,继续在b中查找其对象是否存在,若存在则删除此人及其对象
5.最后按要求输出
6.可惜超时
参考代码2:
#include<iostream>
#include<set>
using namespace std;
/*
解题思路:
*/
int a[50001][2];
int n;
int xunzhao(int temp) //对a而言,如果在二维数组中没有就返回0,如果有就返回其对应的值
{
for(int i=0; i<n; i++)
{
for(int j=0; j<2; j++)
if(a[i][j]==temp)
if(j==0)
return a[i][1];
else
return a[i][0];
}
return 100000;
}
int main()
{
cin >> n;
for(int i=0; i<n; i++)
for(int j=0; j<2; j++)
cin >> a[i][j];
set<int> b;
set<int>::iterator itb;
int m,flag=0;
cin >> m;
for(int i=0; i<m; i++)
{
int temp;
cin >> temp;
b.insert(temp);
}
//消除在此set中有配偶的
for(itb=b.begin(); itb!=b.end(); itb++)
{
if(xunzhao(*itb)!=100000)
if(b.find(xunzhao(*itb))!=b.end())
{
b.erase(xunzhao(*itb));
b.erase(*itb);
}
}
cout << b.size() << endl;
for(itb=b.begin(); itb!=b.end(); itb++)
{
if(flag!=0)
cout << " ";
cout << *itb;
flag++;
}
return 0;
}
1066
参考代码1:
#include<iostream>
using namespace std;
int main()
{
int m,n,a,b,k;
cin >> m >> n >> a >> b >> k;
int l[n];
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
cin >> l[j];
for(int j=0; j<n; j++)
{
if(j!=0)
cout << " ";
if(l[j]<a || l[j]>b)
printf("%03d",l[j]);
else
printf("%03d",k);
}
cout << endl;
}
return 0;
}
参考代码2:
#include<iostream>
using namespace std;
int main()
{
int m,n,a,b,k,temp;
cin >> m >> n >> a >> b >> k;
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
scanf("%d",&temp); //不用设置数组来存放,因为在循环中如果有一个输入,一个输出,如果一次性全部输入,那么对应的输出也是一次性全部输出,并非输入一个就显示一个。这里如果用cin输入就会超时
if(temp>=a && temp<=b)
temp=k;
if(j!=0)
cout << " ";
printf("%03d",temp);
}
cout << endl;
}
return 0;
}
1067
解题思路1:
1.while设置为死循环
2.还是输入一个,输出一个,不是等到全部输入完后在输出
3.如果是正确的密码且尝试次数不超过 N,则在一行中输出 Welcome in,并结束程序;
如果是错误的,则在一行中按格式输出 Wrong password: 用户输入的错误密码;
当错误尝试达到 N 次时,再输出一行 Account locked,并结束程序
就按照这个策略去构建代码,不要自己胡推
参考代码1:
#include <iostream>
using namespace std;
/*
解题思路:
*/
int main()
{
string password, temp;
int n, cnt = 0;
cin >> password >> n;
getchar();
while(1)
{
getline(cin, temp);
if (temp == "#")
break;
cnt++;
if (cnt <= n && temp == password)
{
cout << "Welcome in";
break;
}
else if (cnt <= n && temp != password)
{
cout << "Wrong password: " << temp << endl;
if (cnt == n)
{
cout << "Account locked";
break;
}
}
}
return 0;
}
注意事项:
1.在上面代码中不要忘记在第一次输入完后再输入getchar()接受缓冲区中的回车,以方便后面在循环中继续输入
2.此题的思路并非等所有输入完后在输出
解题思路2:
1.如果是正确的密码且尝试次数不超过 N,则在一行中输出 Welcome in,并结束程序
2.如果是错误的,则在一行中按格式输出 Wrong password: 用户输入的错误密码
3.当错误尝试达到 N 次时,再输出一行 Account locked,并结束程序。
4.用while开始输入,统计当前输入的个数,
参考代码2:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
/*
解题思路:
*/
int main()
{
string mima,temp="ds";
int n,count=1;
cin >> mima >> n;
scanf("\n");
vector<string> a;
while(temp.compare("#")!=0)
{
getline(cin,temp);
a.push_back(temp);
}
for(int i=0; i<a.size(); i++)
{
if(a[i].compare(mima)!=0 && count<=n)
{
printf("Wrong password: ");
cout << a[i] << endl;
}
if(a[i].compare(mima)!=0 && count>n)
{
cout << "Account locked";
return 0;
}
if(a[i].compare(mima)==0 && count>n)
{
cout << "Account locked";
return 0;
}
if(a[i].compare(mima)==0)
{
cout << "Welcome in";
return 0;
}
count++;
}
return 0;
}
1068
解题思路1:
1.第一行和第1列肯定都不要想,最后一行,一列的值也不要想
2.还是用二维数组去存储
3.用该值去见上下的,左右的,主队角线上的,副对角线上的差值必须大于tol才行
参考代码1:
#include<iostream>
using namespace std;
/*
解题思路:
*/
int main()
{
int m,n,tol,cnt=0,s,b;
cin >> m >> n >> tol;
int a[n][m];
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
cin >> a[i][j];
}
for(int i=1; i<n-1; i++)
{
for(int j=1; j<m-1; j++)
{
if(a[i][j]-a[i][j-1]>tol && a[i][j]-a[i][j+1]>tol && a[i][j]-a[i-1][j]>tol && a[i][j]-a[i+1][j]>tol && a[i][j]-a[i-1][j-1]>tol && a[i][j]-a[i+1][j+1]>tol && a[i][j]-a[i-1][j+1]>tol && a[i][j]-a[i+1][j-1]>tol)
{
s=i;
b=j;
cnt++;
}
}
}
if(cnt==1)
printf("(%d, %d): %d",b+1,s+1,a[s][b]);
else if(cnt>1)
cout << "Not Unique";
else if(cnt==0)
cout << "Not Exist";
return 0;
}
解题思路2:
1.设置一个2维数组v,dir表示该点周围的8个点的位置(按照顺时针的顺序)
2.判断该点是否符合要求的函数judge
1.循环是8次
2.i,j分别表示行和列
3.tx,ty分别表示i,j周围的点的坐标
4.tx取值范围是0–n-1,ty取值范围是0–m-1,v[i][j]-v[tx][ty]<=tol或者v[i][j]-v[tx][ty]>=-tol,返回false
3.将2维数组设为n行m列的数组
4.按照行-列的顺序依次输入,并且mapp[i][j]++,表示该数字必须只有1个
5.用双层for循环统计符合要求的数字的个数cnt
6.最后根据cnt的值按要求输出
参考代码2:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
/*
解题思路:
*/
int m, n, tol;
vector<vector<int>> v;
int dir[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1},{0, -1}};
bool judge(int i, int j)
{
for (int k = 0; k < 8; k++)
{
int tx = i + dir[k][0]; //行,下面代码中i是从0~n-1
int ty = j + dir[k][1]; //列,下面代码中j是从0~m-1
//tx,ty分别表示周围8个点的坐标,它的意思是直接判断这些坐标所代表的值是否符合要求,自动排除了,所有第1行(列),最后1行(列)的点
if (tx >= 0 && tx < n && ty >= 0 && ty < m && v[i][j] - v[tx][ty] >= 0 - tol && v[i][j] - v[tx][ty] <= tol)
return false;
}
return true;
}
int main()
{
int cnt = 0, x = 0, y = 0;
cin >> m >> n >> tol; //m是列,n是行
v.resize(n, vector<int>(m)); //resize(),设置大小(size); 设置一个n行,每一行放一个长度为m的数组
map<int, int> mapp;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> v[i][j];
mapp[v[i][j]]++; //这个mapp表示比如在输入样例1中 0有8个,65280有23个。。。
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (mapp[v[i][j]] == 1 && judge(i, j) == true)
{
cnt++;
x = i + 1;
y = j + 1;
}
}
}
}
注意事项:
1.其实并不是所有第1行(列),最后1行(列)的点不考虑,这些点只与剩下的3或者5个点比较
2.对于输入样例1,其实16711479和16711680都合适,为啥结果只有16711680,因为16711479满足条件的有2个
1069
解题思路1:
1.先判断输入的字符串在之前是否存在,如果是就s=s+1(s表示要输出的位置)
2.当i==s时,并且这个位置的字符串之前没有
1.先mapp[str]设为1
2.输出
3.改变合适的位置s
4.设置一个flag初值为0,如果有中奖的则把flag改为1
3.当循环结束时,根据flag的值看是否输出Keep going…
参考代码:
#include <iostream>
#include <map>
using namespace std;
/*
解题思路:
*/
int main()
{
int m, n, s;
cin >> m >> n >> s;
string str;
map<string, int> mapp;
bool flag = false;
for (int i = 1; i <= m; i++)
{
cin >> str;
if (mapp[str] == 1)
s+=1;
if (i == s && mapp[str] == 0) //按照规定的间隔输出,还要保证之前没有得过奖
{
mapp[str] = 1;
cout << str << endl;
flag = true;
s+=n;
}
}
if (flag == false)
cout << "Keep going...";
return 0;
}
1070
解题思路:
1.将这个数字排序
2.从最小的两个开始就一路计算
参考代码:
/*
解题思路:
*/
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int a[n];
for(int i=0; i<n; i++)
cin >> a[i];
sort(a,&a[n]); //默认为从小到大
double sum=(double)(a[0]+a[1])/2;
for(int i=2; i<n; i++)
{
sum=(sum+a[i])/2;
}
cout << (int)sum;
}