d1 . 求整数段和
坑点 : 当刚好输出5的倍数的数量时要小心连续换行
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
int tot = 0;
int sum = 0;
for(int i = a; i <= b;i++){
tot++;
sum += i;
if(tot%5 == 0 && tot != b - a + 1) printf("%5d\n",i);
//太细节了防止最后一个字符再换行,当然也可以|| tot = b - a + 1,去掉下面的endl
else printf("%5d", i);
}
cout<<endl<<"Sum = "<<sum;
return 0;
}
倍数的数量,原先程序会导致连续换两次行
2. 二分法求多项式单根(暂时未解)
坑点 :
3. 龟兔赛跑
坑点 : 第10的倍数的分钟时兔子要先跑完再决定摆不摆烂,也许是我sb了
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
int bailan = 0;
int s1 = 0,s2 = 0;
for(int i = 1;i <= n;i++){
s1 += 3;
if(bailan != 0) {bailan--;}//我大兔子要摆烂啦
else{
s2 += 9;//先跑完再决定要不要摆烂
if(i % 10 == 0&&s2 > s1){
bailan = 30;//开摆!
}
}
}
if(s1 > s2) cout<<"@_@ "<<s1;
if(s1 == s2) cout<<"-_- "<<s1;
if(s1 < s2) cout<<"^_^ "<<s2;
return 0;
}
4. 约分最简分式
难点 :稍微了解下gcd算法
自己的代码:
#include<iostream>
using namespace std;
int main(){
int a,b;
char ch;
cin>>a>>ch>>b;
int min;
while(1){
if(a < b) min = a;
else min = b;
for(int i = min;i > 1;i--){
if(a%i == 0&&b%i == 0){
a /= i;
b /= i;
continue;
}
}
break;
}
cout<<a<<"/"<<b;
return 0;
}
gcd :
#include<stdio.h>
int gcd(int a,int b){
int r=a%b;
while(r){
a=b;
b=r;
r=a%b;
}
return b;
}
int main(){
int a,b;
scanf("%d/%d",&a,&b);
int n=gcd(a,b);
printf("%d/%d",a/n,b/n);
}
(3.20更新)精简版:
int gcd(int a,int b) { // 求最大公约数
return !b?a:gcd(b,a%b);
}
5. 说反话
难点 :字符串没有明显的结束字符例如'.'
解决方法 : stringstream
//stirngstream可以用于分割被空格、制表符等符号分割的字符串
#include<bits/stdc++.h>
using namespace std;
int main(){
stringstream stream;
vector<string> vec;
string s;
getline(cin,s);
stream<<s;
while(stream>>s){
vec.push_back(s);
}
for(int i = vec.size() - 1;i >= 0;i--){
if(i == 0) cout<<vec[i];
else{
cout<<vec[i]<<" ";
}
}
return 0;
}
6. 通讯录的录入与显示
难点:结构体的考察
坑点 :c++不能定义变量名为”data“的数据 会导致ambiguous(摸棱两可)
//每行按照格式姓名 生日 性别 固话 手机给出一条记录。其
//对每一条要查询的记录编号,在一行中按照姓名 固话 手机 性别 生日的格式输出该记录。若要查询的记录不存在,则输出Not Found。
#include<bits/stdc++.h>
using namespace std;
struct Comuni{
string name;
string birth;
char gender;
string fixedphone;
string phone;
}cdata[11];//原为data导致编译错误
int main(){
int n;
cin>>n;
for (int i = 0;i < n;i++){
cin>>cdata[i].name>>cdata[i].birth>>cdata[i].gender>>cdata[i].fixedphone>>cdata[i].phone;
}
int k;
cin>>k;
while(k--){
int search;
cin>>search;
if(search>n - 1||search < 0){
cout<<"Not Found"<<endl;
}
else{
cout<<cdata[search].name<<" "<<cdata[search].fixedphone<<" "<<cdata[search].phone<<" "<<cdata[search].gender<<" "<<cdata[search].birth<<endl;
}
}
return 0;
}
7. 有理数均值
坑点 : 不用gcd算法超时。。本来想混的
正确 代码 :
//分子和分母全是整形范围内的整数;如果是负数,则负号一定出现在最前面。
//若分母为1,则只输出分子。
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
int r=a%b;
while(r){
a=b;
b=r;
r=a%b;
}
return b;
}
int main(){
int n;
cin>>n;
int kee = n;
--n;
int a1,b1;
char ch;
cin>>a1>>ch>>b1;
while(n--){
int a2,b2;
cin>>a2>>ch>>b2;
int temp = b1;
a1 *= b2;
b1 *= b2;
a2 *= temp;
b2 *= temp;
a1 += a2;
int maxg = gcd(a1,b1);
a1 /= maxg;
b1 /= maxg;
}
b1 *= kee;
int maxg = gcd(a1,b1);
a1 /= maxg;
b1 /= maxg;
if(b1 == 1) cout<<a1;
else cout<<a1<<"/"<<b1;
return 0;
}
8 . 复数四则运算
坑点:输入时两位小数,输出确实一位小数是否等于0要用fabs(a)<0.1 判断
#include<bits/stdc++.h>
using namespace std;
double a1, b1, a2, b2;
void ccout(double a,char c, double b)
{
if (b1 >= 0 && (b2 >=0))
printf("(%.1lf+%.1lfi) %c (%.1lf+%.1lfi) = ", a1, b1, c, a2, b2);
else if ((b1 >= 0) && (b2 < 0))
printf("(%.1lf+%.1lfi) %c (%.1lf%.1lfi) = ", a1, b1, c, a2, b2);
else if ((b1<0) && (b2 >= 0))
printf("(%.1lf%.1lfi) %c (%.1lf+%.1lfi) = ", a1, b1, c, a2, b2);
else
printf("(%.1lf%.1lfi) %c (%.1lf%.1lfi) = ", a1, b1, c, a2, b2);
if (fabs(a)<0.1 && fabs(b)<0.1) { printf("0.0\n"); return; }
int flag = 0; //用来标记看是否实部有输出,好解决虚部的符号问题
if (fabs(a)>=0.1)
{
printf("%.1lf", a);
flag++;
}
if (fabs(b)>=0.1){
if (flag && b > 0.0)printf("+%.1lfi", b);
else printf("%.1lfi", b);
}
cout << endl; //无论什么结果都要输出回车
}
int main()
{
cin >> a1 >> b1 >> a2 >> b2;
double a, b;
//加法
a = a1 + a2;
b = b1 + b2;
ccout(a, '+', b);
//减法
a = a1 - a2;
b = b1 - b2;
ccout(a, '-', b);
//乘法
a = a1*a2 - b1*b2;
b = a1*b2 + a2*b1;
ccout(a, '*', b);
//除法
a = (a1*a2 + b1*b2) / (a2*a2 + b2*b2);
b = (a2*b1 - a1*b2) / (a2*a2 + b2*b2);
ccout(a, '/', b);
return 0;
}
9 . 整数分解为若干项之和
难点 : DFS快忘了。。。。并且当next == n时(最后一项时)不用输出;
#include<bits/stdc++.h>
using namespace std;
int flag = 0, n, a[35];
void dfs(int len, int pos, int next) //len当前长度,pos当前用了多大值,下一个要加的值的大小
{
if (pos + next > n)return; //如果值大于N就没有继续的必要了
a[len++] = next; //保存路径
if (pos+next == n){
cout << n << "=";
for (int i = 0; i < len; i++){
if (i == 0) cout << a[i];
else cout << "+" << a[i];
}
if (++flag % 4 == 0||next == n)cout << endl; //每输出四个一次回车
else cout << ";"; //每行输出最后一个不带分号
}
if (pos + next < n)
{
pos += next;
for (int i = next; i <= n - pos; i++)//根据规律得出后面的i>=next
dfs(len, pos, i);
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n / 2; i++) //i小于n/2,防止7=3+4、7=4+3该类情况
dfs(0, 0, i);
dfs(0, 0, n); //7=7的时候特殊处理
return 0;
}
10 . 数列求和-加强版
坑点:全部相加完tmp不等于0还要输出tmp
#include <iostream>
using namespace std;
int ans[1000000];
int main() {
int A, N, tmp = 0;
cin >> A >> N;
if (N) {
for (int i = 0, j = N; i < N; ++i, --j) {
tmp += (A * j);
ans[i] = tmp % 10;
tmp /= 10;
}
if(!tmp) cout<<tmp;//point!!
for (int i = N - 1; i >= 0; --i)
cout << ans[i];
}
else
cout << 0;
return 0;
}
11 . 素数对猜想
坑点 : 观察素数 2 3 5 7 11 13 17 19 23...除了第一对(2,3)其他至少相差2,并且第一对相差不等于2不符题意不用理会,所以要尽可能地优化地查找下一个素数(跨两个找)要不然只有18分
//“素数对猜想”认为“存在无穷多对相邻且差为2的素数”
#include<bits/stdc++.h>
using namespace std;
bool prime(int a){
int i=2;
for(;i<=sqrt(a)+1;i++){
if(a%i==0){
return false;
}
}
return true;
}
int main(){
int n;
cin>>n;
int res = 0;
int pn1 = 3,pn2 = 5;//prime number
while(pn2 <= n){
if(pn2 - pn1 == 2){
res++;
}
pn1 = pn2;
for(int i = pn2 + 2;i < n+10;i+=2){
if(prime(i)){
pn2 = i;
break;
}
}
}
cout<<res;
return 0;
}
2022.11.7三刷代码
#include<iostream>
#include<vector>
using namespace std;
bool isprime(int x){
if(x < 2) return false;
for(int i = 2;i * i <= x;i++){
if(x % i == 0) return false;
}
return true;
}
int main(){
int n;
cin >> n;
vector<int> v;
for(int i = 2;i <= n;i++){
if(isprime(i)) v.push_back(i);
}
int res = 0;
for(int i = 1;i <= v.size();i++){
if(v[i] - v[i - 1] == 2) res++;
}
cout << res;
}
12 . 福尔摩斯的约会
真的狗题浪费我半小时。。。
//前面两字符串中第 1 对相同的大写英文字母
//后面两字符串第 1 对相同的英文字母 s 出现在第 4 个位置(从 0 开始计数)
#include<bits/stdc++.h>
using namespace std;
int main(){
map<char, string> m;
m['A'] = "MON";
m['B'] = "TUE";
m['C'] = "WED";
m['D'] = "THU";
m['E'] = "FRI";
m['F'] = "SAT";
m['G'] = "SUN";
string s1,s2,s3,s4;
cin>>s1;
cin>>s2;
cin>>s3;
cin>>s4;
int s1max = min(s1.size(),s2.size());
int s2max = min(s3.size(),s4.size());
int fir,sec,thi;
for(int i = 0; i < s1max;i++){
if(s1[i] == s2[i] && s1[i] >='A'&&s1[i] <= 'G'){
fir = i;
break;
}
}
cout<<m[s1[fir]]<<" ";
for(int i = fir + 1; i < s1max;i++){
if(s1[i] == s2[i]&&(isdigit(s1[i])||(s1[i] >= 'A'&&s1[i] <= 'N'))){
if(isdigit(s1[i])) cout<<"0"<<s1[i];
else cout<<s1[i] - 'A' + 10;
break;
}
}
cout<<":";
for(int i = 0; i < s2max;i++){
if(s3[i] == s4[i] && isalpha(s3[i])){
if(i < 10) cout<<"0"<<i;
else cout<<i;
break;
}
}
return 0;
}
2022.11.7三刷代码
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<string> v = {" ","MON","TUE","WED","THU","FRI","SAT","SUN"};
string s1,s2;
int week, hour, minute;
int tmp;
cin >> s1 >> s2;
int len1 = s1.size(), len2 = s2.size();
for(int i = 0;i < min(len1,len2);i++){
if(s1[i] == s2[i] && s1[i] >= 'A' && s1[i] <= 'G'){
week = s1[i] - 'A' + 1;
tmp = i;
break;
}
}
for(int i = tmp + 1;i < min(len1,len2);i++){
if(s1[i] == s2[i]){
if(isdigit(s1[i])){
hour = s1[i] - '0';
break;
}
else if(s1[i] >= 'A' && s1[i] <= 'N') {
hour = 10 + s1[i] - 'A';
break;
}
}
}
cin >> s1 >> s2;
for(int i = 0;i < min(s1.size(), s2.size());i++){
if(s1[i] == s2[i] && isalpha(s1[i])){
minute = i;
break;
}
}
cout << v[week] << " ";
printf("%02d:%02d",hour,minute);
}
13 . 部分 A + B
难点 :
string和数值转换 | 转换类型 |
---|---|
to_string(val) | 把val转换成string |
stoi(s,p,b) | 把字符串s从p开始转换成b进制的int |
stol(s,p,b) | 把字符串s从p开始转换成b进制的long |
stoul(s,p,b) | 把字符串s从p开始转换成b进制的unsigned long |
stoll(s,p,b) | 把字符串s从p开始转换成b进制的long long |
stoull(s,p,b) | 把字符串s从p开始转换成b进制的unsigned long long |
stof(s,p) | 把字符串s从p开始转换成float |
stod(s,p) | 把字符串s从p开始转换成double |
stold(s,p) | l把字符串s从p开始转换成long double |
#include<bits/stdc++.h>
using namespace std;
int main(){
string a,b;
char da,db;
cin>>a>>da>>b>>db;
int numa = 0,numb = 0;//有多少个da/db
for(auto m : a){
if(m == da){
numa++;
}
}
for(auto m : b){
if(m == db){
numb++;
}
}
string resa = " ",resb = " ";
for(int i = 1;i <= numa;i++){
resa += da;
}
for(int i = 1;i <= numb;i++){
resb += db;
}
int ra,rb;//int类型
if(resa == " ") ra = 0;
else ra = stoi(resa);
if(resb ==" ") rb = 0;
else rb = stoi(resb);
int res = ra + rb;
cout<<res;
return 0;
}
2022.11.7三刷代码
#include<iostream>
#include<string>
using namespace std;
int main(){
int num1, num2;
int d1, d2;
cin >> num1 >> d1 >> num2 >> d2;
string s1 = to_string(num1);
string s2 = to_string(num2);
string res1 , res2;
for(int i = 0;i < s1.size();i++){
if(s1[i] - '0'== d1) res1 += s1[i];
}
for(int i = 0;i < s2.size();i++){
if(s2[i] - '0' == d2) res2 += s2[i];
}
if(res1.empty() && res2.empty()) cout << 0;
else if(res1.empty()) cout << stoi(res2);
else if(res2.empty()) cout << stoi(res1);
else cout << stoll(res1) + stoll(res2) << endl;
}
14 . 挖掘技术哪家强
确实是道送分题但是。。。
我的G点 :后面还用到n就不能while(n--),都要用for循环保险!!!!!!!!
还有一个坑就是 : max最好设成-1
#include<bits/stdc++.h>
using namespace std;
int school[100001]={0};
int main()
{
int n,schID,score;
cin>>n;
for(int i = 0 ; i<n;i++)
{
scanf("%d %d",&schID,&score);
school[schID] += score;
}
int k = 1 ,MAX = 0;
for(int i=1;i<=n;i++)
{
if(MAX<school[i])
{
k=i;
MAX=school[i];
}
}
printf("%d %d\n",k,MAX);
return 0;
}
2022.11.7表示送命题
#include<iostream>
#include<map>
using namespace std;
int main(){
int n;
cin >> n;
map<int,int> map;
while(n--){
int a, b;
cin >> a >> b;
map[a] += b;
}
int maxn = -1e9;
int id;
for(auto c : map){
if(c.second > maxn){
maxn = c.second;
id = c.first;
}
}
cout << id << " " << maxn;
}
15 . 完美数列
难点:经过简单观察,优化时尽量优化for的第一项而非第二项!
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
long long p;
cin>>n>>p;
vector<int> a(n);
for(int i = 0; i < n;i++){
cin>>a[i];
}
sort(a.begin(),a.end());
int res = 0;
for(int i = 0; i < n;i++){
for(int j = i + res;j < n;j++){
if(a[j] <= a[i] * p){
res = max(res,j - i + 1);
}
else{
break;
}
}
}
cout<<res;
return 0;
}
2022.11.7三刷
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
long long n, p;
cin >> n >> p;
vector<long long> v(n);
for(int i = 0;i < n;i++) cin >> v[i];
sort(v.begin(),v.end());
long long res = 1;
int j = 0;
for(int i = 0;i < n;i++){
while(j < n - 1 && v[j + 1] <= v[i] * p) j++;
res = max(res, j - i + 1ll);
}
cout << res << endl;
}
16 . 月饼
难点: 销售时允许取出一部分库存
意味着可以选择一点数据而非全选,解决方法 :结构体
//N 表示月饼的种类数
//D 表示市场最大需求量
//每种月饼的库存量 每种月饼的总售价
#include<bits/stdc++.h>
using namespace std;
struct item{
double cap;//容量
double price;//单价
}moon[1001];
bool cmp(item a,item b){
return a.price > b.price;
}
int main(){
int n,d;
double res = 0.0;
cin>>n>>d;
for(int i = 1; i <= n;i++){
cin>>moon[i].cap;
}
for(int i = 1;i <= n;i++){
cin>>moon[i].price;
moon[i].price /= moon[i].cap;
}
sort(moon + 1,moon + n + 1,cmp);
for(int i = 1; i <= n;i++){
if(d <= moon[i].cap){
res += moon[i].price * d;
break;
}
else{
res += moon[i].price * moon[i].cap;
d -= moon[i].cap;
}
}
printf("%.2f",res);
return 0;
}
17 . 旧键盘打字
难点 : 字符串若为空则不能用cin,要用getline
//如果上档键坏掉了,那么大写的英文字母无法被打出。
//字符串若为空则不能用cin,要用getline
#include<bits/stdc++.h>
using namespace std;
int main(){
string s1,s2;
getline(cin,s1);
getline(cin,s2);
for(int i = 0 ;i < s2.size();i++){
if(s1.find(toupper(s2[i]))!= string::npos){
continue;
}
else if(s1.find('+') != string::npos &&isupper(s2[i])){
continue;
}
cout<<s2[i];
}
cout<<endl;
return 0;
}
18 . 插入与归并
难点 : 无法简单判断归并排序的当前程度,要从头开始模拟,
//插入排序某个数后开始与原始序列相同
#include<bits/stdc++.h>
using namespace std;
int a[101],b[101];
int main(){
int n;
cin>>n;
for(int i = 0; i < n;i++){
cin>>a[i];
}
for(int i = 0 ;i < n;i++){
cin>>b[i];
}
int begin = 0;
while(b[begin] <= b[begin + 1]&&begin<n - 1){
begin++;
}
int end = begin + 1;
while(a[end] == b[end] && end < n){
end++;
}
if(end == n) {
cout<<"Insertion Sort" << endl;
sort(a,a + begin + 2);
for(int i = 0 ;i < n;i++){
if(i != 0) cout<<" ";
cout<<a[i];
}
}
else {
cout<<"Merge Sort" << endl;///因为并不知道中间序列是归并排序的第几轮,所以只能从第一轮开始模拟归并排序a,直到a和b相等,然后再进行一轮排序就好
int k = 1;//倍数
int flag = 1;//判断是否是最后一轮
while(flag){
flag = 0;
for(int i = 0 ;i < n;i++){
if(a[i] != b[i]){
flag = 1;//不是最后一轮要再进行
break;
}
}
k *= 2;
int i;
for( i = 0; i < n / k;i++){
sort(a + i * k, a + (i + 1) * k);
}
sort(a + i * k,a + n);//防止末尾误差
}
for(int i = 0 ;i < n;i++){
if(i != 0) cout<<" ";
cout<<a[i];
}
}
return 0;
}
19 . 数字加密
难点 : 当b或a的长度不相等时,按题意意思要将短的补满’0‘(a大于b的位数时按要求偶数位要等于10 - a对应的位数)所以要特殊考虑。
//对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 12;对偶数位,用 B 的数字减去 A 的数字,若结果为负数,则再加 10。这里令个位为第 1 位。
//这里令个位为第 1 位。
//错误原因 : a比b长时要将b补0
#include<bits/stdc++.h>
using namespace std;
char kee[13] = {'0','1','2','3','4','5','6','7','8','9','J','Q','K'};
int main(){
string a,b,res;
cin>>a>>b;
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());//反转
int isodd = 1;//当前b是否为奇数位
if(a.size() >= b.size()){//b的每位数都要加密
b.append(a.length() - b.length(),'0');//补充
for(int i = 0; i < b.size();i++){
if(isodd){
res += kee[((b[i] - '0' + a[i] - '0') % 13)];
isodd = 0;
}
else{
int num = b[i] - a[i];
if(num < 0){
num += 10;
}
res += to_string(num);
isodd = 1;
}
}
//发生错误 a>b时偶数位不等于a原来的数。。。。 res += a.substr(b.size(),a.size() - //b.size());
}
else{//b有些数字不需要加密
for(int i = 0; i < a.size();i++){
if(isodd){
res += kee[((b[i] - '0' + a[i] - '0') % 13)];
isodd = 0;
}
else{
int num = b[i] - a[i];
if(num < 0){
num += 10;
}
res += to_string(num);
isodd = 1;
}
}
res += b.substr(a.size(),b.size() - a.size());
}
reverse(res.begin(),res.end());
cout<<res;
return 0;
}
2022.11.7优化
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string s1, s2;
cin >> s1 >> s2;
string res;
int ji = 1;
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
while(s1.size() < s2.size()) s1 += '0';
while(s2.size() < s1.size()) s2 += '0';
for(int i = 0;i < s2.size();i++){
if(i >= s1.size()) res += s2[i];
else if(ji){
int num = (s1[i] - '0' + s2[i] - '0') % 13;
if(num < 10) res += to_string(num);
if(num == 10) res += 'J';
if(num == 11) res += 'Q';
else if(num == 12) res += 'K';
ji ^= 1;
}
else{
int num = s2[i] - s1[i];
if(num < 0) num += 10;
res += to_string(num);
ji ^= 1;
}
}
int index = 0;
reverse(res.begin(),res.end());
for(int i = index;i < res.size();i++){
cout << res[i];
}
}
20 . 数列的片段和
坑点 : 不是子集问题并且用dfs超时,要用数学方法
//不是子集问题,题目要连续的字串
#include<bits/stdc++.h>
using namespace std;
vector<double> nums;
vector<double> tmp;
vector<vector<double>> re;
double res = 0.0;
void dfs(vector<double> num,int index){
if(index > num.size()) return;
if(tmp.size() != 0) {//防止空集
re.push_back(tmp);
for(int i = 0 ; i < tmp.size();i++){
res += tmp[i];
}
}
tmp.push_back(nums[index]);
dfs(nums,index + 1);
tmp.pop_back();
}
int main(){
int n;
cin>>n;
for(int i = 0; i < n;i++){
double num;
cin>>num;
nums.push_back(num);
}
for(int i = 0; i < nums.size();i++){
dfs(nums,i);
}
printf("%.2f",res);
return 0;
}
正确代码 :
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
long long sum = 0;//不用long long还是会炸
double temp;
for (int i = 1; i <= n; i++) {
cin >> temp;
sum += (long long)(temp * 1000) * i * (n - i + 1);temp前面的指针有i种选择,后面的指针有n - i + 1种选择
}
printf("%.2f", sum / 1000.0);
return 0;
}
引用 牛人原话 :“N比较大时,double类型的值多次累加导致的精度误差,因为输入为十进制小数,存储到double中时,计算机内部使用二进制表示,且计算机的字长有限,有的十进制浮点数使用二进制无法精确表示只能无限接近,在字长的限制下不可避免会产生舍入误差,这些细微的误差在N较大时多次累加会产生较大误差,所以建议不要使用double类型进行多次累加的精确计算,而是转为能够精确存储的整型。尝试把输入的double类型的值扩大1000倍后转为long long整型累加,同时使用long long类型保存sum的值,输出时除以1000.0转为浮点型再输出(相当于把小数点向后移动3位后再计算,避免double类型的小数部分存储不精确,多次累加后对结果产生影响)
但我觉得乘以1000也未必严谨,可能测试样例最小只有小数点后三位,如果测试样例变成小数点后四位、五位、六位,乘以1000相当于直接在小数点后三位处截断,而原本第四五六位经过多次累加进位后依然可能会引起精度问题,但如果乘以10000就会超出long long的值,我认为最精确的应该是截取到所有小数中最大的位数的那一位。。可能我的想法有疏漏,经过测试,测试样例确实没有超过小数点后三位,虽然修改为乘以1000后代码已经AC,但如果对测试样例稍加修改,可能又会导致不AC了…所以这道题先打个问号吧,我猜可能将来题目样例还会被修改…”
2022.11.7 发现 直接开long double就行
#include<iostream>
using namespace std;
int main(){
long n;
cin >> n;
long double res = 0;
long tmp = n;
for(long i = 1;i <= n;i++){
long double x;
cin >> x;
res += x * i * (tmp--);
}
printf("%.2Lf",res);
}
21 . 复数乘法
坑点 :当A或者B小于0但是大于-0.005(比如-0.00001)时候,如果按照A>=0的判断,会输出“-0.00”这样的结果,事实上应该输出“0.00”【B同理,应该输出“+0.00i”】
#include<bits/stdc++.h>
using namespace std;
int main(){
double a,ai,b,bi;
cin>>a>>ai>>b>>bi;
double A=a*b*cos(ai)*cos(bi)-a*b*sin(ai)*sin(bi);
double B=a*b*cos(ai)*sin(bi)+a*b*sin(ai)*cos(bi);
if (A + 0.005 > 0 && A < 0)//3.11修改 :不应该>=(当-0.005输出-0.01)
printf("0.00");
else
printf("%.2f", A);
if(B >= 0)
printf("+%.2fi", B);
else if (B + 0.005 > 0 && B < 0)
printf("+0.00i");
else
printf("%.2fi", B);
return 0;
}
22 . 火星数字
坑点 :第一次输入n后不能直接getline,不然会get第一行而不是第二行
解决方法 :getchar()定位下一个字符
#include<bits/stdc++.h>
using namespace std;
string a[13] = {"tret","jan","feb","mar","apr","may","jun","jly","aug","sep","oct","nov","dec"};//1 - 12 对应的数
string b[13] = {"####","tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};//进制后的
void tohuo(int t){
if(t/13) //有进制数
{
cout<<b[t/13];
if(t % 13) {//题目样例tam说明刚好进制的数不用加tret
cout<<" "<<a[t%13];
}
}
else cout<<a[t%13];//没进制数
}
void todi(string s){
int res1 = 0,res2 = 0;
string s1,s2;
int n2 = s.size();
s1 = s.substr(0,3);
if(n2 > 4) s2 = s.substr(4,3);
for(int i = 1 ;i < 13;i++){
if(s1 == a[i] || s2 == a[i]) res1 = i;//第二种情况没进制位
if(s1 == b[i]) res2 = i;
}
cout<<13 * res2 + res1;
}
int main(){
int n;
cin>>n;
getchar();
while(n--){
string s;
getline(cin,s);
if(s[0] >= '0' && s[0] <= '9') tohuo(stoi(s));
else todi(s);
cout<<endl;
}
return 0;
}
2022.11.7三刷:似乎更长了?
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main(){
vector<string> low = {"tret", "jan", "feb", "mar", "apr", "may", "jun", "jly","aug", "sep", "oct", "nov", "dec"};
vector<string> high = {" ", "tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};
int n;
cin >> n;
getchar();
while(n--){
string s;
getline(cin, s);
if(isdigit(s[0])){
int num = stoi(s);
string fir = high[num / 13];
string sec = low[num % 13];
if(fir != " ") cout << fir;
if(fir != " " && sec != "tret") cout << " ";
if(sec != "tret" || (sec == "tret" && fir == " "))cout << sec;
cout << endl;
}
else{
if(s.size() > 4){
string s1 = s.substr(0,3);
string s2 = s.substr(4);
int res = 0;
for(int i = 0;i < high.size();i++){
if(s1 == high[i]){
res += i * 13;
break;
}
}
for(int i = 0;i < low.size();i++){
if(s2 == low[i]){
res += i;
break;
}
}
cout << res << endl;
}
else{
int res;
for(int i = 0;i < low.size();i++){
if(low[i] == s){
res = i;
break;
}
}
for(int i = 0;i < high.size();i++){
if(high[i] == s){
res = i * 13;
break;
}
}
cout << res << endl;
}
}
}
}
23 . 快速排序
坑点 :双重for循环超时 并且没有主元时还要多输出一个endl!(输出两行)
如数组1 5 3 4 2,排列后是1 2 3 4 5,显然按照索引位置不变即主元判断的话,会得到主元为1 3 4的错误答案,正确答案应为1。也就是,排序前后改变位置的一定不是主元,但主元不一定改变位置。
测试点3和5便是测试的以上问题,主元不仅要排列前后索引位置不变,而且要大于它索引之前的所有数,题目说明了输入的是N个不同的数,不需要考虑元素相同情况
//双重for循环导致超时
#include<bits/stdc++.h>
using namespace std;
vector<int> res;
int main(){
int n;
cin>>n;
int a[n],b[n];
for(int i = 0 ; i < n;i++){
cin>>a[i];
b[i] = a[i];
}
sort(b,b + n);
int maxn = 0;//截至到i为止最大的数
for(int i = 0; i < n;i++){
if(a[maxn] < a[i]) maxn = i;
if(i == maxn && a[i] == b[i]) res.push_back(a[i]);//若到i为止i为最大元素并且小于右边的任何元素则符合
}
cout<<res.size()<<endl;
for(int i = 0; i < res.size();i++){
if(i != 0) cout<<" ";
cout<<res[i];
}
cout<<endl;//无语
return 0;
}
24 . 求平均值
![](https://img-blog.csdnimg.cn/b725aeb751a84eae8cbc6fec7eb1d710.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBARnV0dXJlIE5vdCBUaXJlZA==,size_20,color_FFFFFF,t_70,g_se,x_16)
真滴恶心 :首先就是
是number不是numbers!!!!!!!
最恶心的就是形如 123.不是error!!!!!!
//123.也行。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。!!!!!!!!!
#include<bits/stdc++.h>
using namespace std;
double sum = 0;
int number = 0;
int main(){
int n;
cin>>n;
for(int i = 0 ; i < n;i++){
string s;
cin>>s;
bool isnum = 1;//是否符合
int pointnum = 0;//小数点的数量
int pointindex;//小数点的位置
for(int j = 0 ; j < s.size();j++){
if(j == 0 && s[j] == '-'){
continue;
}
if(s[j] == '.'){
pointnum++;
pointindex = j;
continue;
}
else if(!isdigit(s[j])) {
isnum = 0;
break;
}
}
if(isnum == 0 || pointnum > 1){//不符
cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
}
else if(pointnum == 1 && ((s.size() - 1 - pointindex > 2))){//一个小数点但多于两位小数 ,居然允许最后一位是小数点
cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
}
else if(stod(s) < -1000.0 || stod(s) > 1000.0){
cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
}
else{
sum += stod(s);
number++;
}
}
if(number == 0){
cout<<"The average of 0 numbers is Undefined";
}
else if(number == 1){
cout<<"The average of "<<number<<" number is ";
printf("%.2f",sum/number);
}
else{
cout<<"The average of "<<number<<" numbers is ";
printf("%.2f",sum/number);
}
return 0;
}
2022.11.7三刷
#include<string>
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
int legal = 0;
double res =0;
for(int i = 1;i <= n;i++){
string s;
cin >> s;
int point = 0;
bool islegal = true;
int index = -1;
for(int i = 0;i < s.size();i++){
if(i == 0 && s[i] == '-') continue;
else if(isdigit(s[i])) continue;
else if(!isdigit(s[i]) && s[i] == '.'){
if(index == -1){
index = i;
}
else islegal = false;
}
else islegal = false;
}
if(s.size() > 9) islegal = 0;
if(index != -1 && s.size() - index > 3) islegal = 0;
if(islegal ) {
if(stod(s) > 1000.0 || stod(s) < -1000.0) islegal = 0;
}
if(!islegal){
cout << "ERROR: " << s << " is not a legal number" << endl;
}
else{
legal++;
res += stod(s);
}
}
if(legal == 1){
printf("The average of %d number is %.2f",legal, 1.0 * res / legal);
}
else if(legal > 1){
printf("The average of %d numbers is %.2f",legal, 1.0 * res / legal);
}
else{
printf("The average of %d numbers is Undefined",legal);
}
}
25 . 狼人杀
评价 :思维火花
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> v(n+1);
for(int i = 1; i <= n;i++) cin>>v[i];
for(int i = 1; i <= n;i++){
for(int j = i + 1;j <= n;j++){//假设第i和j是狼
vector<int> lie,wolf(n+1,1);
wolf[i] = wolf[j] = -1;
for(int k = 1; k <= n;k++){//判断第k个是不是狼人
if( v[k] * wolf[abs(v[k])] < 0){//第k个人所猜的人
lie.push_back(k);
}
}
if(lie.size() == 2 && wolf[lie[0]] + wolf[lie[1]] == 0){//就一个狼人不都在撒谎
cout<<i<<" "<<j;
return 0;
}
}
}
cout<<"No Solution";
return 0;
}
26 . 谷歌的招聘
难点1 :首先就是num.size()返回的是unsigned int类型的数,当L<K是本来会负数,但是用num.size()-K得到的是极大的正数,所以会继续循环。。
如22行的 //for(int i=0; i<=s.length()-K; i++)
解决方法 :用(int)L替代num.size(),(其实本就不应该用num.size())
然后这种大位数整数的子整数问题首先想到用string解决(substr可以提取整个string的一部分,而不用模拟加法)
//测试点4:num是string类型的,而num.size()返回的是unsigned int类型的数,当L<K是本来会负数,但是用num.size()-K得到的是极大的正数,所以会继续循环。。
#include<bits/stdc++.h>
using namespace std;
bool isPrimer(int n)
{
if (n <= 1)return false;
for (int i=2; i * i <= n; i++)
{
if (n%i==0)
return false;
}
return true;
}
int main()
{
int L,K,p;
cin>>L>>K;
getchar();
string s,b;
getline(cin,s);
for(int i=0; i<=L-K; i++)// 原错误点:for(int i=0; i<=s.length()-K; i++)
{
b=s.substr(i,K);//从i开始取长度为K的字符串
p=stoi(b);//z将字符串转换为整数
if(isPrimer(p))
{
cout<<b;
return 0;
}
}
cout<<"404";
return 0;
}
2022.11.7 三刷
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
int l, k;
cin >> l >> k;
string s;
cin >> s;
if(k > l) {
cout << "404";
return 0;
}
auto check = [&](int x){
if(x < 2) return false;
for(int i = 2; i * i <= x; i++){
if(x % i == 0) return false;
}
return true;
};
for(int i = 0; i <= l - k; i++){
if(check(stoi(s.substr(i, k)))){
cout << s.substr(i, k);
return 0;
}
}
cout << "404";
}