A 【字符串】ISBN号码(字符串基础)
字符串基础题,注意一下x的特判即可
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
string a;
int p=1,sum=0;
cin>>a;
for(int i=0;i<a.size()-1;i++)
if(isdigit(a[i]))
sum+=(a[i]-'0')*p++;
sum%=11;
if(sum==10)
{
if(a[a.size()-1]=='X')
cout<<"Right";
else
{
for(int i=0;i<a.size()-1;i++)
cout<<a[i];
cout<<'X';
}
}
else
{
if(char(sum+'0')==a[a.size()-1])
cout<<"Right";
else
{
for(int i=0;i<a.size()-1;i++)
cout<<a[i];
cout<<char(sum+'0');
}
}
}
B 第N个智慧数(数学)
打表题
解法
把所有的平方差都枚举一下
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
cout<<i*i-j*j;
这样还会出现重复的项,并且还是乱序的,我是打出表来之后再把他们放到set中进行进行去重与排序然后输出即可
代码
#include <bits/stdc++.h>
using namespace std;
int bk[]={这里是打表};
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
set<int> st;
for(int i=0;i<4950;i++)
st.insert(bk[i]);
int n,sum=0;
cin>>n;
for(auto it=st.begin();it!=st.end();it++)
{
sum++;
if(sum==n)
{
cout<<*it;
break;
}
}
}
C 第m大的身份证号码(字符串基础)
这个把他们用个sort排序一下就可以了
代码
#include <bits/stdc++.h>
using namespace std;
string num[1666],num1[666];
bool cmp(string a,string b)
{
string t1="",t2="";
for(int i=6;i<=13;i++)
t1+=a[i];
for(int i=6;i<=13;i++)
t2+=b[i];
return t1<t2;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++)
cin>>num[i];
sort(num,num+n,cmp);
cout<<num[k-1];
}
D 锯木棍(模拟)
这个题直接模拟即可
解法
因为涂色,所以我们可以把这个木块当一个桶,涂色等于桶上的点放入了东西。因为涂两种颜色且两种颜色都是长度的约数,因此我们可以直接进行扫描
第一遍扫描扫最大值
第二遍扫描扫等于最大值的数量
代码
#include <bits/stdc++.h>
using namespace std;
int bk[100015];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int l,m,n,maxn=-1,sum=0,ans=0;
cin>>l>>m>>n;
int s1=l/m;
int s2=l/n;
for(int i=1;i<=l;i++)
if(i%s1==0)
bk[i]=1;
for(int i=1;i<=l;i++)
if(i%s2==0)
bk[i]=1;
for(int i=1;i<=l;i++)
{
if(bk[i]==0)
sum++;
else
{
sum++;
maxn=max(maxn,sum);
sum=0;
}
}
for(int i=1;i<=l;i++)
{
if(bk[i]==0)
sum++;
else
{
sum++;
if(sum==maxn)
ans++;
sum=0;
}
}
cout<<maxn<<" "<<ans;
}
E 坐标统计(基础编程能力)
直接放入然后扫描比较即可
代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x,y;
}zb[10000];
int sum[10000];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,maxn=-1,id;
cin>>n;
for(int i=0;i<n;i++)
cin>>zb[i].x>>zb[i].y;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(zb[j].x<zb[i].x&&zb[j].y<zb[i].y)
sum[i]++;
for(int i=0;i<n;i++)
{
if(sum[i]>=maxn)
{
maxn=sum[i];
id=i+1;
}
cout<<sum[i]<<"\n";
}
cout<<id;
}
F 打印月历(基础编程能力)
可能这个题分到基础编程能力有点感觉不大合适,但是这个题确实没有别的什么难的知识点只是需要注意一些地方
解法
①首先就是这个闰年的问题,闰年的2月还平年的2月是不一样的
②然后是计算这月距离第一个月的第一天有几天
③然后推出这个月的第一天是在星期几
int t=(sum)%7;
int day=(n+t-1)%7+1;
其中day变量就是星期几
④之后再算出这个月具体多少天,这个还得分闰年和平年
⑤然后按照1到这个月的天数输出即可(这里之前还要把那些空格打印出来)
⑥注意第一行一定没有空行要不格式错误(测试数据 2015 2 4)
⑦还有数字用%-4d
代码
#include <bits/stdc++.h>
using namespace std;
int month[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
int main()
{
/*ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);*/
int y,m,n,yn;
cin>>y>>m>>n;
cout<<"S M T W T F S\n";
if(y%4==0&&y%100!=0||y%400==0)
yn=1;
else
yn=0;
int c=m-1,mth,sum=0;
for(int i=1;i<c+1;i++)
{
if(i==2)
{
if(yn)
sum+=29;
else
sum+=28;
}
sum+=month[i];
}
int t=(sum)%7;
int day=(n+t-1)%7+1;
for(int i=0;i<(day%7)*4;i++)
cout<<" ";
if(m==2)
{
if(yn)
mth=29;
else
mth=28;
}
else
mth=month[m];
int ft=1;
for(int i=1;i<=mth;i++)
{
if(day==7)
{
if(!ft)
cout<<"\n";
day=0;
}
printf("%-4d",i);
day++;
ft=0;
}
}
G 分割绳子(二分查找)
这个地方比赛的时候,都已经做出来了,就是因为二分查找带小数的东西有些细节不会找,导致的出现了问题
对于小数点的精度问题,我们不能单纯的用l<=r而是用带精度的
这个题我们要精确到小数点后两位,那么我们可以用
while(l<=r-0.001)
//do something
其中mid也是double的,之前l=mid+1也变成了l=mid+0.001 r也相同的道理
这个题原题应该没有什么问题吧,裸二分查找
判断函数也是判断一下当前mid值能分割出几个绳子即可
代码
#include <bits/stdc++.h>
using namespace std;
double num[1005];
int n,k;
int isok(double m)
{
int sum=0;
for(int i=0;i<n;i++)
sum+=num[i]/m;
return sum>=k;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
double l=0,r;
cin>>n>>k;
for(int i=0;i<n;i++)
cin>>num[i],r=max(r,num[i]);
while(l<=r-0.001)
{
double mid=(l+r)/2;
if(isok(mid))
l=mid+0.001;
else
r=mid-0.001;
}
printf("%.2f",l-0.001);
}
H 换座位(语法基础)
排序一次跟原来比较一下看哪里不一样了
代码
#include <bits/stdc++.h>
using namespace std;
int num[666],num1[666];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,sum=0;
cin>>n;
for(int i=0;i<n;i++)
cin>>num[i],num1[i]=num[i];
sort(num,num+n);
for(int i=0;i<n;i++)
if(num[i]!=num1[i])
sum++;
cout<<sum;
}
I 找M进制数(字符串基础)
这个题我还因为细节问题罚时两次
需要注意的细节
①十进制以下是否出现了字母或者大于等于当前进制的数
②十进制以上是否出现了大于等于当前进制的字母
③第一位数字是否为0(听说这个数据中好像没有给出)、
代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x,y;
}zb[10000];
int sum[10000];
string st[100005];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,maxn=-1,id;
cin>>n>>id;
int ans=n;
for(int i=0;i<n;i++)
cin>>st[i];
for(int i=0;i<n;i++)
for(int j=0;j<st[i].size();j++)
{
if(st[i][0]=='0')
{
ans--;
break;
}
if(id<=10)
{
if(isalpha(st[i][j]))
{
ans--;
break;
}
if(isdigit(st[i][j]))
{
if(st[i][j]-'0'>id-1)
{
ans--;
break;
}
}
}
if(id>10)
{
if(isalpha(st[i][j]))
{
if(st[i][j]>'A'+id-11)
{
ans--;
break;
}
}
}
}
cout<<ans;
}
J 循环小数(字符串模拟)
这个题并不难啊,比起紫书上那个90年代的acm世界决赛的真题来说还是太嫩了点
解法
①找出循环节前的小数
②找出循环节
③把循环节循环多次加到循环节前的小数后面(这里一定要比给定的要找的位数要多)
④按照要求输出即可
代码
#include <bits/stdc++.h>
using namespace std;
int bk[100015];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,f=0,ff=0;
cin>>n;
string a,nu="",xh="";
cin>>a;
for(int i=0;i<a.size();i++)
{
if(a[i]=='.')
f=1;
if(a[i]=='(')
ff=1;
if(f&&!ff)
{
if(isdigit(a[i]))
nu+=a[i];
}
if(f&&ff)
{
if(isdigit(a[i]))
xh+=a[i];
}
}
for(int i=0;i<100005;i++)
nu+=xh;
cout<<nu[n-1];
}
K 单纯质因数(数论)
当时一直打表还不知道哪里打错了,实际上这个题可以直接暴力去做
我这里又学到了一种O(N根号(N))的分解质因数的算法
这里可以直接用朴素的思想,如果他没有相同的质因数,那么肯定就是把所有的质因数乘起来就等于原来的说
好,我们用这个思想去做,从2到n每个数枚举一遍看他是不是质因数
然后就超时了,因为O(N*N)对于1e5来说还是太大了(当然你可以打表啊,打出5万以内的素数表)
这里介绍一种O(N*根号(N))的分解因数的方法
for(int j=2;j*j<=i;j++)
{
if(i%j==0)
{
if(isp(j))
sum*=j;
if(i/j!=j&&isp(i/j))
sum*=(i/j);
}
}
这里第一个条件就是朴素的找到质因数,第二个条件就是如果这个数除以找到的这个数不等于原来的(符合条件一不同的因数)且是质数(符合条件二是质因数)
代码
#include <bits/stdc++.h>
using namespace std;
int isp(int n)
{
for(int i=2;i*i<=n;i++)
if(n%i==0)
return 0;
return 1;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=6;i<=n;i++)
{
if(isp(i))
continue;
int jk=1;
for(int j=2;j*j<=i;j++)
if(i%j==0)
{
if(isp(j))
jk*=j;
if(i/j!=j&&isp(i/j))
jk*=(i/j);
if(jk==i)
{
cout<<i<<" ";
break;
}
}
}
}
L 安装饮水机(贪心)
实际上这个就是经典的区间选点问题的贪心,把给的数据化成一个一个的区间然后贪心即可
代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l,r;
}num[10000];
bool cmp(node a,node b)
{
return a.r==b.r?a.l>b.l:a.r<b.r;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int t1,t2;
cin>>t1>>t2;
int l=t1-t2;
int r=t1+t2;
if(l<0)
l=0;
num[i].l=l;
num[i].r=r;
}
sort(num,num+n,cmp);
int now=num[0].r,ans=1;
for(int i=1;i<n;i++)
if(num[i].l>now)
{
ans++;
now=num[i].r;
}
cout<<ans;
}
M 分木块(语法基础)
代码
#include <bits/stdc++.h>
using namespace std;
int num[666],num1[666];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,sum=0,r1=0,r2=0,r3=0;
cin>>n;
for(int i=0;i<n;i++)
{
int t,ans1=0,ans2=0,ans3=0;
cin>>t;
ans1+=t/100;
t%=100;
ans2+=t/10;
t%=10;
ans3+=t;
r1+=ans1;
r2+=ans2;
r3+=ans3;
}
cout<<r1<<"\n"<<r2<<"\n"<<r3;
}
N 活动人数(语法基础)
代码
#include <bits/stdc++.h>
using namespace std;
int num[1666],num1[666];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,sum=0,r1=0,r2=0,r3=0,l,k;
cin>>n>>l>>k;
for(int i=0;i<n;i++)
cin>>num[i];
sort(num,num+n);
for(int i=0;i<n;i++)
if(1)
{
if(l>=num[i])
{
sum++;
l+=k;
}
}
cout<<sum;
}