决战11月之——PTA中的大坑/难题(超级大重点)

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 . 求平均值

真滴恶心 :首先就是 

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";
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值