2022JK工作室第三次招新赛题解

本文介绍了多个算法问题的思路和解决方案,涉及找规律、素数判断、打印图案、字符串着色、数字转换等多个方面。通过C++代码展示了解题过程,包括计算中位数、判断闰年、转换进制等,适合提升编程和算法能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1820,来自gmf二号的问候

思路解析:找规律

参考代码:

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int n;
	cin>>n;
	int num=0;
	int result=0;
	int k=0;//保存1 2 3 4 5 6,每次奇数和偶数的个数
	if(n==1)
    {
		cout<<"1";
	}
    else if(n==2)
	{
		cout<<"2";
	}
	else
    {
        for(int i=1;i<n;i++)
        {
            num+=i;
            if(num>=n)
            {
                k=num-n;   
                result=i*i;
                break;
            }
        }
//建议带入例子,自己模拟一下
        if(k!=0)
        {
            for(int i=1;i<=k;i++) //可以理解为回退
            {
                result-=2;
            }
            cout<<result;
        }
        else      
        {
            cout<<result;
        }
	}
	return 0;
}

1821,来自gmf一号的问候

思路解析:在不大于n的整数中先判断出素数,然后再判断其各数为上是否出现k即可

参考代码:

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int arr[10001];
int check(int a,int k)  //判断a中各数位是否含有b
{
	while(a)
	{
		if(a%10==k){
			return 0;
		}
		a/=10;
	}
	return 1;
}
int main()
{
	int n,k;
	cin>>n>>k;
	int s=0;
	int num=0;
	for(int j=2;j<=n;j++)
    {
                int flag=1;
            for(int i=2;i<=sqrt(j);i++)  //判断素数
            {
                if(j%i==0)
                {
                    flag=0;
                }
            }
            if(flag) //flag为1,则代表其为素数
            {
                if(check(j,k))
                {
                    num++;
                }
            }
	}
	cout<<num<<endl;
	return 0;
} 

 或

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int arr[10001];
int check(int a,int k)  //判断a中各数位是否含有b
{
	while(a)
	{
		if(a%10==k){
			return 0;
		}
		a/=10;
	}
	return 1;
}
int main()
{
	int n,k;
	cin>>n>>k;
	int s=0;
	int num=0;
	for(int j=0;j<n;j++)
    {
		if((n-j)!=1)
        {
                int flag=1;
            for(int i=2;i<=sqrt(n-j);i++)  //判断素数
            {
                if((n-j)%i==0)
                {
                    flag=0;
                }
            }
            if(flag) //flag为1,则其为素数
            
            {
                if(check(n-j,k))
                {
                    num++;
                }
            }
		}
	}
	cout<<num<<endl;
	return 0;
} 

1822,来自gmf三号的问候

思路解析:打印沙漏,打印三角形即可实现

参考代码:

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int n,m;
	cin>>n;
	m=2*n-1;
	for(int i=1;i<=n;i++)
    {
		for(int j=1;j<=m-i+1;j++)
        {
			if(j<=i-1) cout<<" ";
			else cout<<"*";
		}
        cout<<endl;
	}
	for(int i=n+1;i<=m;i++)
    {
		for(int j=1;j<=n+(i-n);j++)
        {
			if(j<n-(i-n)) cout<<" ";
			else cout<<"*";
		}
         cout<<endl;
	}
    return 0;
}

1823,来自szw的问候

思路解析:思维题,如题意所示,满足四个条件的情况下称为精彩着色。相同的字母数量再多,最多也就只能涂上两种色。所以多于2个的某种字母的多余部分无效。也就是说一种字母再多,最多有两个涂色了(最多贡献两个)。

想法一:对于每种字母,最多填一个红色,一个绿色,当这个字母的数量不少于 2 时,它对答案的贡献为 1。而对于只有一个的字母,每一个字母填红色,就要有一个字母填绿色,设所有个数为1的字母的数量为 n,则对答案的贡献为 n/2(向下取整)。

想法二:算出出现次数<=2的字母个数/2(出现次数<=2的色块均可上色,非红即绿),直接出答案。

参考代码:

想法一:

#include<iostream>
#include<cstring>
using namespace std;
string s;
int a[30];
int ans,tot;
void work()
{
	ans=tot=0;
	cin>>s;
	for(int i=0;i<s.length();i++)
    {
        a[s[i]-'a']++;
    }
	for(int i=0;i<26;i++)
	{
		if(a[i]>=2)
        {
            ans++;
        }
		if(a[i]==1)
        {
            tot++;
        }
	}
	ans+=tot/2;
	printf("%d\n",ans);
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
    {
        work();
    }
	return 0;
}

想法二:

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		char s[51];
		scanf("%s",s);
		int c[26]={},t=0;
		for(int i=0;s[i]!='\0';i++)
		{
			c[s[i]-'a']++;
			if(c[s[i]-'a']<3)  t++;
		}
		printf("%d\n",t/2);
	}
	return 0;
}

1824,来自ly的问候

思路解析:


​参考代码:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int a[200];
char s[100010];
int main()
{
    scanf("%s",s);

    int str=strlen(s);

    for(int i=0;i<str;i++)
    {
        a[s[i]-'0']++;
    }

    for(int i=0;i<str;i++)
    {
        if(a[s[i]-'0']==1)
        {
            printf("%d\n",i);
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}

 1825,来自hry的问候

思路解析:难点在于读题

 参考代码:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
    string s;   //读入
    string  res;  //输出答案
    cin>>s;
    int count[26]={};  //记录出现多少次
    int str=s.size();
    for(int i=0;i<str;i++)
    {
        count[s[i]-'a']++;
    }
    while(res.size()<s.size())
    {
        for(int i=0;i<26;i++)  //升序
        {
            if(count[i]>0)
            {
                res+=i+'a';
                count[i]--;
            }
        }
        for(int i=25;i>=0;i--) //降序
        {
            if(count[i]>0)
            {
                res+=i+'a';
                count[i]--;
            }
        }
    }
    cout<<res<<endl;
    return 0;
}

附上原题链接:(点我即可)!

1826,来自zjy的问候

思路解析:求出中位数(之前做过),并将其转换为二进制即可

———————————————————————————————————————————

十进制转换二进制

整数

十进制整数转换为二进制整数采用"除2取余,逆序排列"法。

具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为小于1时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来

十进制整数转二进制

如:255=(11111111)B

255/2=127=====余1

127/2=63======余1

63/2=31=======余1

31/2=15=======余1

15/2=7========余1

7/2=3=========余1

3/2=1=========余1

1/2=0=========余1

789=1100010101(B)

789/2=394 余1 第10位

394/2=197 余0 第9位

197/2=98 余1 第8位

98/2=49 余0 第7位

49/2=24 余1 第6位

24/2=12 余0 第5位

12/2=6 余0 第4位

6/2=3 余0 第3位

3/2=1 余1 第2位

1/2=0 余1 第1位

原理

众所周知,二进制的基数为2,我们十进制化二进制时所除的2就是它的基数。谈到它的原理,就不得不说说关于位权的概念。对于多位数,处在某一位上的“1”所表示的数值的大小,称为该位的位权 。位权的大小是以基数为底,数字符号所处的位置的序号为指数的整数次幂。例如十进制第2位的位权为10,第3位的位权为100;而二进制第2位的位权为2,第3位的位权为4,百位、十位、个位、十分位的权分别是10的2次方、10的1次方、10的0次方,10的-1次方。二进制数就是2的n次幂。

按权展开求和正是非十进制化十进制的方法。

下面我们开讲原理,举个十进制整数转换为二进制整数的例子,假设十进制整数A化得的二进制数为edcba 的形式,那么用上面的方法按权展开, 得

A=a(2^0)+b(2^1)+c(2^2)+d(2^3)+e(2^4) (后面的和不正是化十进制的过程吗)

假设该数未转化为二进制,除以基数2得

A/2=a(2^0)/2+b(2^1)/2+c(2^2)/2+d(2^3)/2+e(2^4)/2

注意:a不能整除2,但其他的能整除,因为他们都包含2,而a乘的是1,他本身绝对不包含因数2,只能余下。

商得:

b(2^0)+c(2^1)+d(2^2)+e(2^3),再除以基数2余下了b,以此类推。

当这个数不能再被2除时,先余掉的a位数在原数低,而后来的余数数位高,所以要把所有的余数反过来写。正好是edcba

小数

十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,此时0或1为二进制的最后一位。或者达到所要求的精度为止。

然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。

十进制小数转二进制

如:0.625=(0.101)B

0.625*2=1.25======取出整数部分1

0.25*2=0.5========取出整数部分0

0.5*2=1==========取出整数部分1

再如:0.7=(0.1 0110 0110...)B

0.7*2=1.4========取出整数部分1

0.4*2=0.8========取出整数部分0

0.8*2=1.6========取出整数部分1

0.6*2=1.2========取出整数部分1

0.2*2=0.4========取出整数部分0

0.4*2=0.8========取出整数部分0

0.8*2=1.6========取出整数部分1

0.6*2=1.2========取出整数部分1

0.2*2=0.4========取出整数部分0

原理:

关于十进制小数转换为二进制小数

假设一十进制小数B化为了二进制小数0.ab的形式,同样按权展开,得

B=a(2^-1)+b(2^-2)

因为小数部分的位权是负次幂,所以我们只能乘2,得

2B=a+b(2^-1)

注意a变成了整数部分,我们取整数正好是取到了a,剩下的小数部分也如此。

值得一提的是,小数部分的按权展开的数位顺数正好和整数部分相反,所以不必反向取余数了。

———————————————————————————————————————————

参考代码:

#include<iostream>
#include<algorithm>
using namespace std;
int n;
int a[110];
void check(int n){
	int i=0;
	while(n!=0){
		a[i]=n%2;
		n/=2;
		i++;
	}
	i--;
	for(;i>=0;i--)
    {
		cout<<a[i];
	}
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)  cin>>a[i];
 
	sort(a,a+n);
 
	if(n%2!=0)
	{
		// printf("%d",a[n/2]);
        check(a[n/2]);
	}
	else if(n%2==0)
	{
		if((a[n/2-1]+a[n/2])%2==0)   //中间两个数的和可以整除2
		{
			// printf("%d",(a[n/2-1]+a[n/2])/2);
            check((a[n/2-1]+a[n/2])/2);
		}
		else  //中间两个数的和无法整除2 
		{
			// printf("%.1f",(double)(a[n/2-1]+a[n/2])/2);
            check((double)(a[n/2-1]+a[n/2])/2);
            cout<<".1"<<endl;
		}
	}
	return 0;
}

1827,来自hsq的问候

思路解析:本题数据量过大,枚举必然超时,所以需要改变思路。

不妨对区间开根号减小数据,开根号之后默认向下取整,那么右边界无需考虑,唯一需要考虑的就是左边界。

1.当a*a=m,即左边界也为一个完全平方数,默认向下取整对结果无影响,直接b-a+1即可得到答案。(例如:1,36; 答案为1,2,3,4,5,6;即6-1+1=6)

2.当a*a!=m,左边界不是一个完全平方数,默认向下取整可能使得改变了原来的区间,因此需要a+1来保证区间。(例如17,36;17开根号为4,答案为5,6;即6-(4+1)+1)

建议自己带入例子思考!!!!!!!!!!

参考代码:

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
ll m,n;
int main()
{
    cin>>m>>n;
    ll a=sqrt(m);
    ll b=sqrt(n);
    if(a*a==m)
    {
        cout<<b-a+1;
    }
    else 
    {
        cout<<b-(a+1)+1;
    }
    return 0;
}

1828,来自xyq的问候

思路解析:考察大家判断闰年知识

参考代码:

#include<iostream>
#include<algorithm>
using namespace std; 
int run[12]={31,29,31,30,31,30,31,31,30,31,30,31};
int ping[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
    int a,b,c;
    scanf("%d,%d,%d",&a,&b,&c);
    int sum=0;
    if(a%400==0||(a%4==0&&a%100!=0))
    {
        for(int i=0;i<b-1;i++)   sum+=run[i];

        cout<<sum+c<<endl;
    }
    else 
    {
        for(int i=0;i<b-1;i++)   sum+=ping[i];

        cout<<sum+c<<endl;
    }
    return 0;
}

 1829,来自zzj的问候

思路解析:左右两边同时比较是否相等即可

参考代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int main()
{
    cin>>n;
    while(n--)
    {
        char a[200];
        cin>>a;
        int str=strlen(a);
        int c=0;
        for(int i=0,j=str-1;i<=str/2;i++,j--)
        {
            if(a[i]!=a[j])
            {
                c=1;
            }
        }
        if(c==0)  cout<<"yes"<<endl;
        else  cout<<"no"<<endl;
    }
    return 0;
}

 来自另一位大佬的代码:利用reverse函数

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int m;
	cin>>m;
	while(m--)
    {
        string a;
        string b;
        cin>>a;
        b=a;
        reverse(a.begin(),a.end());
        if(a==b)
        {
            cout<<"yes"<<endl;
        }
        else cout<<"no"<<endl;
    }
    return 0;
}

1830,来自wxy的问候

思路解析:十进制转换为三进制,同十进制转换为二进制方法一样,在此不再赘述

参考代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    while(cin>>n)
    {
        int a[50];
        int i=0;
        while(n)
        {
            a[i++]=n%3;
            n/=3;
        }
        for(int j=i-1;j>=0;j--)
        {
          cout<<a[j];
        }
      cout<<endl;
    }
    return 0;
}

  以上就是关于此次的题解,以上代码仅供参考,答案不唯一,切勿照搬照抄!!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值