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;
}
以上就是关于此次的题解,以上代码仅供参考,答案不唯一,切勿照搬照抄!!!