2021牛客寒假算法基础集训营1


比赛链接

问题F:对答案一时爽

签到题,上去就是wa三发,后面知道了要输入带空格的字符串,然后因为对getline的不熟悉,继续wa两发,后面直接字符输入,奇怪的是scanf不行,cin输入就ok

错误代码:

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    int n;
    cin >> n;
    char s[110],ss[110];
    for(int i=1;i<=n;++i) scanf("%c",&s[i]);
    for(int i=1;i<=n;++i) scanf("%c",&ss[i]);
    int a=0;
    for(int i=1;i<=n;++i)
    {
        if(s[i]==ss[i]) a++;
    }
    int ans1=n+a;
    int ans2=0;
    printf("%d %d\n",ans1,ans2);
    return 0;
}

AC代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	char s[110],ss[110];
	for(int i=1;i<=n;++i) cin>>s[i];
	for(int i=1;i<=n;++i) cin>>ss[i];
	int a=0;
	for(int i=1;i<=n;++i)
	{
		if(s[i]==ss[i]) a++;
	}
	int ans1=n+a;
	int ans2=0;
	cout<<ans1<<" "<<ans2<<endl;
	return 0;
}

这里的标程学到了不少,getchar的c++写法cin.get();getline需要吸收换行,还有一种去除字符串空格的骚操作

标程:

#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
int n;
int main(){
    int i,j;
    string a,b;
    cin>>n;
    cin.get();

    getline(cin, a, '\n');
    getline(cin, b, '\n');
    a.erase(remove_if(a.begin(), a.end(), ::isspace), a.end());
    b.erase(remove_if(b.begin(), b.end(), ::isspace), b.end());
    int cnt=0;
    for(i=0;i<n;i++)if(a[i]==b[i])cnt++;
    cout<<n+cnt<<" "<<0;

}

问题B:括号

想到了a*b+c=k,这样子的形式去构造,思维题就是,想到了就快
先开根号,找出a,然后剩下的除以a,求出b,先输出a个"(",在第c个位置输出一个“)”,然后继续输出b个")";

AC代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int k;
	cin >> k;
	if(k==0) {
		cout<<"(\n";
		return 0;
	}
	int a=(int)sqrt(k); //cout<<a; 
	int b=k-a*a;
	for(int i=1; i<=a;++i) cout<<"(";
	for(int i=1; i<=b/a;++i) cout<<"(";
	b%=a;
	for(int i=1,j=a;i<=a;++i,--j)
	{
		if(j==b) cout<<"(";
		cout<<")";
	}	
	return 0;
}

标程:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,i;
    cin>>n;
    if (n == 0) {
        cout << ")(" << endl;
    }
    else {
        int p=sqrt(n);
        int c=n/p,y=n%p;
        for(i=0;i<y;i++)printf("(");
        printf(")");
        for(;i<p;i++)printf("(");
        for(i=0;i<c;i++)printf(")");
    }
}

问题I:限制不互素对的排列

数学不好真的没办法= =,题目说k<=n/2;只需找出(k+1)个偶数从小到大排列,然后再将其他输出就好了。需要特判k<6&&k==n/2的时候,因为取不到6,形成不了,所以此时为-1。

AC代码:

#include<bits/stdc++.h>
using namespace std;
vector<int>v;
int n,k;

int main()
{
	cin >> n >> k;
	if(n<6 && k==n/2) {
		cout<<-1;
		return 0;
	}
	for(int i=2;i<=n;i+=2)
	{
		if(i!=6) v.push_back(i);
	}
	v.push_back(6);
	v.push_back(3);
	set<int>s;
	for(int i=0;i<=k;++i)
	{
		cout<<v[i]<<' ';
		s.insert(v[i]);
	}
	for(int i=1;i<=n;++i)
	{
		if(!s.count(i))//判断是否是s中元素 
		{
			cout<<i<<' ';
		}
	}
	return 0; 
}

问题E:三棱锥之刻

作为高中数学还过得去的我,推了下公式,三种情况好的差不多,当场就wa,后面才知道少考虑了种情况tmd (菜是原罪)
实际上有四种情况:
1.碰不到
2.四个圆
3.圆和三角的交*4
4.正四面体的全部内表面

AC代码:

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
const double s3=sqrt(3);
const double s6=sqrt(6);

int main()
{
	double a,r; cin >> a >> r;
	double d=(s6/12)*a; //三棱锥的内切圆半径 
	double R=sqrt(r*r-d*d);//在内表面涂的圆的半径;
	double ans=0;
	if(r<=d) ans=0;//碰不到; 
	else if(R>=s3/3*a) ans=s3*a*a;//第四种情况,全部内表面 
	else if(R<=s3/6*a) ans=4*pi*R*R;//四个圆
	else { // 最复杂的一种情况, 
		double the=acos(s3*a/6/R);
		double s1=(2*pi/3-2*the)*R*R*6+6*R*R*sin(2*the);
		ans=s1;
	} 
	printf("%.5f\n",ans);
	return 0;
}

第三种情况也不是很复杂,如图就是棕色加红色的十二倍;
在这里插入图片描述

问题H:幂塔

看起来简单= =(结果是最难的)
官方题解:

  • 当n为1时,直接输出a的个位数即可。
  • 当n=2时,如果a的个位数是2、3、7、8,那么需要观察a的十位数是奇数还是偶数。因为a↑↑2=a^a ,而2、3、7、8的幂的个位数是4个一循环,所以只用观察a模4是2还是0就行。
    如果a的个位数是其他的,那么可以直接输出答案:a的个位数是0 1 5 6 9输出本身即可。a个位数是4则输出6。
  • 当n大于2时,由于a↑↑n=a^{a↑↑(n-1)}
    ,而如果a是偶数,a↑↑(n-1模4的值是确定的,所以a↑↑的个位数也是确定的。而如果a是奇数(特指个位数是3和7),那么a↑↑(n-1模4取决于a模4的值。如果a模4为1,那么a↑↑(n-1模4也是1,此时a的个位数是3和7的话,a↑↑的个位数也是3和7,否则应为7和3。a的个位数是{0,1,2,3,4,5,6,7,8,9}时,对应的a↑↑的个位数为{0,1,6,7,6,5,6,3,6,9}。

标程:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int out[10]={0,1,6,7,6,5,6,3,6,9};
int main(){
    ll a,b;
    string A,B;
    cin>>A>>B;
    if(B.length()==1&&B[B.length()-1]=='1'){
        cout<<A[A.length()-1];
        return 0;
    }
    a=(A[A.length()-1]-'0')%10;
    if(A[A.length()-1]=='3'||A[A.length()-1]=='7'){
        if(A.length()==1||(A[A.length()-2]-'0')%2==0){
            cout<<out[a];
        }
        else{
            cout<<a;
        }
        return 0;
    }


    if((a!=2&&a!=8)||(B.length()>1||B[B.length()-1]!='2')){
        cout<<out[a];

    }
    else{
        if(a==2){
        if(A.length()==1||(A[A.length()-2]-'0')%2==0){
            cout<<4;
        }
        else cout<<6;
        }
        else{
            if(A.length()==1||(A[A.length()-2]-'0')%2==0){
            cout<<6;
        }
        else cout<<4;
        }
    }
}

总结

  • 本菜鸡居然一开始去忙H,我也是疯了,莽半天还是wa,后面一看还是有80%的通过还是欣慰了些许;
  • 对于字符串的读取和处理又有了 新的认识,
  • 构造类的题目不会做= =
  • 希望下次不要出现推公式漏情况吧
  • 剩下的题还得慢慢补>=<
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W⁡angduoyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值