签到题
K题 Headphones
题目大意
总共有n对耳机,Yasa已经拿了k对耳机,NIO至少要拿多少只耳机才能保证比Yasa拿更多对,如果不能就输出-1.
考察内容
数学
分析
如果2*k>n,则不存在,输出-1,否则,最多要拿n-k+k+1只,即n+1只
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k;
while(cin>>n>>k){
printf("%d",2*k<=n?n+1:-1);
}
}
H题 Cutting Papers
题目大意
求图示阴影部分六边形和圆的并集面积
考察内容
几何
分析
答案为大正方形的一半加上圆的一半,nn/2+pi(n/2)*(n/2)/2
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
int main(){
int n;
cin>>n;
printf("%lf\n",(double)n*n/2+pi*n*n/8);
}
B题 Watches
题目大意
如果买k块手表,第i块要多花费k*i元,问有m元最多买几块表。
考察内容
二分
分析
在0-n间二分答案
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int a[N],b[N],n,m;
bool check(int k){
for(int i=1;i<=n;i++)b[i]=a[i]+k*i;
sort(b+1,b+n+1);
int sum=0;
for(int i=1;i<=k;i++){
sum+=b[i];
if(sum>m)return 0;
}
return 1;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
while(cin>>n>>m){
for(int i=1;i<=n;i++)cin>>a[i];
int l=1,r=n;
while(l<=r){
int k=(l+r)>>1;
if(check(k))l=k+1;
else r=k-1;
}
cout<<r<<endl;
}
}
基本题
G题 KFC Crazy Thursday
题目大意
求字符串中以’k’ ‘f’ 'c’结尾的回文子串的数量
考察内容
回文树
分析
模板题
//这注释不写也罢
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+7;
struct node{
int next[26];
int len;
int sufflink;
int num;
}tree[N];
int len;
char s[N];
int num;
int suff;
bool addLetter(int pos){
int cur=suff;
int curlen;
int let=s[pos]-'a';
while(1){
curlen=tree[cur].len;
if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos])break;
cur=tree[cur].sufflink;
}
if(tree[cur].next[let]){
suff=tree[cur].next[let];
return 0;
}
num++;
suff=num;
tree[num].len=tree[cur].len+2;
tree[cur].next[let]=num;
if(tree[num].len==1){
tree[num].sufflink=2;
tree[num].num=1;
return 1;
}
while(1){
cur=tree[cur].sufflink;
curlen=tree[cur].len;
if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos]){
tree[num].sufflink=tree[cur].next[let];
break;
}
}
tree[num].num=1+tree[tree[num].sufflink].num;
return 1;
}
void inittree(){
num=2;suff=2;
tree[1].len=-1;tree[1].sufflink=1;
tree[2].len=0;tree[2].sufflink=1;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
long nk=0,nf=0,nc=0;
cin>>len>>s;
inittree();
for(int i=0;i<len;i++){
addLetter(i);
if(s[i]=='k'){
nk+=tree[suff].num;
}
else if(s[i]=='f'){
nf+=tree[suff].num;
}
else if(s[i]=='c'){
nc+=tree[suff].num;
}
}
printf("%ld %ld %ld\n",nk,nf,nc);
}
C题 Bit Transmission
题目大意
对一个01序列询问,询问的结果最多有一次是错的,问能不能确定序列,可以则输出之,否则输出-1.
考察内容
模拟
分析
满足以下条件输出-1:
1、未询问所有点;
2、存在一点询问得到两种结果数量相同;
3、存在多个点询问得到两种结果;
4、不存在点询问得到两种结果,但是有只询问过一次的点。
否则输出串
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int a[N][2];
bool m[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
memset(a,0,sizeof a);
memset(m,0,sizeof m);
int n;
string s;
cin>>n;
int op,p=0;
for(int i=0;i<3*n;i++){
cin>>op>>s;
if(!m[op])m[op]=1,p++;
if(s=="YES")a[op][1]++;
else a[op][0]++;
}
if(p<n){
cout<<-1<<endl;//情况1
return 0;
}
p=0;
for(int i=0;i<n;i++){
if(a[i][1]==a[i][0]){
cout<<-1<<endl;//情况2
return 0;
}
if(a[i][1]&&a[i][0])p++;
}
if(p>1){
cout<<-1<<endl;//情况3
return 0;
}
if(p==0){
for(int i=0;i<n;i++){
if(a[i][0]+a[i][1]==1){
cout<<-1<<endl;//情况4
return 0;
}
}
}
for(int i=0;i<n;i++){
if(a[i][0]>a[i][1])cout<<0;//输出串
else cout<<1;
}
cout<<endl;
return 0;
}