目录
A. Triple Metre
这道题就是看有没有字符串有没有按oxxoxx的规律连续下去,可能出现的情况就是以下4种:
1.字符串长度小于3,都满足;
2.字符串长度大于3,以o开头,就只可能是oxxoxx,以i计数,i%3==0时,a[i]=='o';
3.字符串长度大于3,以x开头,就可能是xoxxoxx,以i计数,(i+2)%3==0时,a[i]=='o';
4.字符串长度大于3,以x开头,还可能是xxoxxox,以i计数,(i+1)%3==0时,a[i]=='o';
#include<stdio.h>
#include<string.h>
int main()
{
char a[1000001];
scanf("%s", a);
int k;
k=strlen(a);
if(a[0]=='o')
{
for(int i=1;i<k;i++)
{
if(i%3==0)
{
if(a[i]!='o')
{
printf("No");
goto endc;
}
}
else if(i%3!=0)
{
if(a[i]!='x')
{
printf("No");
goto endc;
}
}
}
printf("Yes");
}
if(a[0]=='x')
{
if(k>1)
{
if(a[1]=='x')
{
for(int i=2;i<k;i++)
{
if((i+1)%3==0)
{
if(a[i]!='o')
{
printf("No");
goto endc;
}
}
else if((i+1)%3!=0)
{
if(a[i]!='x')
{
printf("No");
goto endc;
}
}
}
}
if(a[1]=='o')
{
for(int i=2;i<k;i++)
{
if((i+2)%3==0)
{
if(a[i]!='o')
{
printf("No");
goto endc;
}
}
else if((i+2)%3!=0)
{
if(a[i]!='x')
{
printf("No");
goto endc;
}
}
}
}
}
printf("Yes");
}
endc:
return 0;
}
B. Counting 2
这道题就是去查找给出的x在原队列中排在什么位置,一开始我用常规的方法去查找,结果超时了。然后改用二分去查找,过了。
这个需要注意的点就是,当x在原队列中不存在时,即low>high时,第一个大于x的下标为n-low。
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int n, q, i, x, c, j;
scanf("%d%d", &n, &q);
int a[n];
for(int i=0;i<n;i++)
{
scanf("%d", &a[i]);
}
sort(a, a+n);
for(i=0;i<q;i++)
{
scanf("%d", &x);
int low=0;
int high=n-1;
int mid=(low+high)/2;
while (low<=high)
{
mid = (low+high)/2;
if (a[mid]==x)
{
printf("%d\n", n-mid);
break;
}
else if (a[mid]>x)
{
high=mid-1;
}
else
{
low=mid+1;
}
}
if (low>high)
printf("%d\n", n-low);
}
return 0;
}
C. Neighbors *
这道题就是排除掉No的情况,其他就是Yes,No有以下情况:
1.当一个人想站一起的人数大于2;
2.当一人想和另外两人站一起时,那两人想站一起;
3.当所有人站成一个环时;
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int d[N];
int f[N];
int p[N];
int find(int x);
int main()
{
int n, m;
scanf("%d%d", &n, &m);
bool f=0;
for (int i=1;i<=n;i++ )
p[i]=i;
for (int i=1;i<=m;i++ )
{
int a, b; cin >> a >> b;
if (find(a)==find(b))
{
printf("No\n");
goto end;
}
p[find(a)]=find(b);
d[a]++;
d[b]++;
}
for (int i=1;i<=n;i++ )
{
if (d[i]>2)
{
printf("No\n");
goto end;
}
}
printf("Yes\n");
end:
return 0;
}
int find(int x)
{
if (p[x]!=x)
{
p[x]=find(p[x]);
}
return p[x];
}
D. X drawing**
E. Sum of difference/
这道题我一开始就是想着去把每一个值都算出来,但写的时候就感觉会超时,结果真超时了。。。
然后我就发现其运算有一定的规律。
#include<cstdio>
#include<algorithm>
#include <iostream>
using namespace std;
long long a[1000000];
long long b[1000000];
int main()
{
int n;
scanf("%d", &n);
for(int i=1;i<=n;i++)
{
scanf("%lld", &a[i]);
}
unsigned long long s=0;
sort(a+1, a+n+1, greater<int>());
for(int i=1;i<=n;i++)
{
b[i]=b[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
s+=b[n-i]-(b[n]-b[i]);
}
printf("%llu", s);
return 0;
}
F. Unlucky 7/
这道题就是先判断n是否含7,有则c++,没有则将n转换为8进制看它是否含7。
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
char buf[10];
int c=0;
for (int i=1;i<=n;i++)
{
sprintf(buf, "%d", i);
string s=string(buf);
if (string::npos != s.find('7', 0))
{
c++;
}
else
{
sprintf(buf, "%o", i);
s=string(buf);
if (string::npos != s.find('7', 0))
{
c++;
}
}
}
printf("%d\n", n-c);
return 0;
}
G. Stamp**
H. Duodecim Ferra**
这道题就是对于长度为L的铁棒,把它分成12段,就相当于从内部的L−1个点中挑选出11个不同的点进行切割。
#include<stdio.h>
int main()
{
int n;
scanf("%d", &n);
long long p=1, c=0;
for(int i=0; i<11; i++)
{
c=p*(n-(i+1))/(i+1);
p=c;
}
printf("%lld\n", c);
return 0;
}
I. Reorder Cards**
这道题想要使用最少的数量覆盖尽可能大的区域,就需要使用尽可能长的邮票来覆盖,因为不能覆盖到蓝色方块,所以我们k的最大取值为夹在蓝色方块中的白色方块数量的最小值。又因为可以重复覆盖,所以对于一个长度为w的白色方块,我们只需要使用(w+k−1)/个邮票就可以。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
vector<int> pos(m);
for(int i=0;i<m;i++)
cin>>pos[i];
pos.push_back(n+1);
vector<int> cnt;
sort(pos.begin(),pos.end());
int pre=0;
int mmin=(int)1e9;
for(int i=0;i<(int)pos.size();i++)
{
int gap=pos[i]-pre-1;
pre=pos[i];
if(!gap) continue;
mmin=min(mmin,gap);
cnt.push_back(gap);
}
long long ans=0;
for(int i=0;i<(int)cnt.size();i++)
ans+=(cnt[i]+mmin-1)/mmin;
cout<<ans;
return 0;
}
J. abc285_brutmhyhiizp
这道题就是读到a b c——x y z就分别返回对应的1 2 3——24 25 26,加到s上。每读取下一位字符,就将原本的s*26,因为每在下一位取一个字符,前面的一位都需要进过26次的重复,所以要乘26。
需要注意的是,这个s可能会很大,我是选择用unsigned long long来表示的。因为它可以存储到1*10的19次方大小。
#include<stdio.h>
#include<string.h>
int abspd(int i);
char a[15];
int main()
{
unsigned long long s=0;
scanf("%s", a);
int k;
k=strlen(a);
int c;
for(int i=0;i<k;i++)
{
s*=26;
c=abspd(i);
s+=c;
}
printf("%llu\n", s);
return 0;
}
int abspd(int i)
{
if(a[i]=='A')
return 1;
else if(a[i]=='B')
return 2;
else if(a[i]=='C')
return 3;
else if(a[i]=='D')
return 4;
else if(a[i]=='E')
return 5;
else if(a[i]=='F')
return 6;
else if(a[i]=='G')
return 7;
else if(a[i]=='H')
return 8;
else if(a[i]=='I')
return 9;
else if(a[i]=='J')
return 10;
else if(a[i]=='K')
return 11;
else if(a[i]=='L')
return 12;
else if(a[i]=='M')
return 13;
else if(a[i]=='N')
return 14;
else if(a[i]=='O')
return 15;
else if(a[i]=='P')
return 16;
else if(a[i]=='Q')
return 17;
else if(a[i]=='R')
return 18;
else if(a[i]=='S')
return 19;
else if(a[i]=='T')
return 20;
else if(a[i]=='U')
return 21;
else if(a[i]=='V')
return 22;
else if(a[i]=='W')
return 23;
else if(a[i]=='X')
return 24;
else if(a[i]=='Y')
return 25;
else if(a[i]=='Z')
return 26;
}
K. Colorful Candies/
这道题就是双指针,通过从左向右滑动窗口,来找到最大值。
#include<iostream>
#include<string>
#include<map>
using namespace std;
const int maxn = 3e5;
map<int,int> m;
int nums[maxn+10];
int c[maxn+10];
int main()
{
int n,k;
cin>>n>>k;
nums[n-k+1]=0;
int cx=0;
int maxx=0;
for(int i=1;i<=n;i++)
{
cin>>c[i];
if(i<=k)
{
if(m.count(c[i])==0)
{
m[c[i]]=1;
cx++;
}
else
{
m[c[i]]++;
}
}
}
maxx=cx;
for(int i=k+1;i<=n;i++)
{
m[c[i-k]]--;
if(m[c[i-k]]==0)
{
cx--;
m.erase(c[i-k]);
}
if(m.count(c[i])==0)
{
m[c[i]]=1;
cx++;
if(cx>maxx)
maxx=cx;
}
else
{
m[c[i]]++;
}
}
cout<<maxx<<endl;
return 0;
}
L. Triangles**
这道题我没什么思路,但看到网上有很多种做法,比如:
首先排序。然后枚举最长的 2 根棍子 i,j(i<j),我们可以得到最短棍子的长度范围,即(l[i]+l[j],l[j]-l[i])。因此,我们可以进行二进制搜索来获得最短的棍子的数量。因为我们按顺序枚举,所以它们不会被重复计算;
对数组进行排序。在两个嵌套循环中,运行二进制搜索:lowerBound 和 upperBound 以查找可以形成有效三角形的第一个和最后一个索引。(这种我感觉好好写一点,但还是没写出来。。。)