这场…没发挥出实力QAQ…连A题我都看了10分钟才知道该怎么写,B写了半个多小时最后还因为一个特判没写fst了…结果妥妥掉分了QAQ..
最终排名:rank850,rating-=52,目前rating1804(离紫名又远了点qwq)…
A. Odds and Ends
题意:给你一堆数,问你能不能分割成奇数个个数为奇数的子串,且所有子串的头尾都为奇数。
思路&&题解:这题我竟然想了10分钟啊QAQ..其实只要判断下数组长度为奇数且开头结尾都是奇数就行了…(没错就这么简单..)
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n;
int a[maxn];
int main() {
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
if(n%2==0||a[1]%2==0||a[n]%2==0) {
puts("No");
return 0;
}
puts("Yes");
return 0;
}
B. Tell Your World
题意:给出坐标为 (i,y[i]) 的一系列点,问能否找到两条平行且不重合的直线,使得所有点都落在两条直线上,且每条直线上至少有一个点。
思路&&题解:我是通过构造两个等差数列然后判断的..先枚举第一个点与第几个点是在同一条线上的,然后就可以通过构造等差数列求出在这条线上的另外还有几个点,之后找到从左往右第一个没有在这条直线上的点,再根据这个公差构造一个等差数列,如果两个等差数列一共覆盖了 n 个点且每个等差数列都至少覆盖到一个点,那么就是可以的。我fst 是因为我没判当第一条直线只经过第一个点的时候斜率是随机选的,我默认他是平行于 x 轴了。。。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int n,a[maxn],tmpx,tmpy;
int x1[maxn],x2[maxn];
bool vis[maxn];
int gcd(int a,int b) {
return b?gcd(b,a%b):a;
}
int main() {
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
x1[1]=a[1];
for(int p=1;p<=n;p++) {
tmpx=p-1;
tmpy=a[p]-a[1];
int tot=0;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)
x1[i]=x2[i]=2e9;
if(tmpx==0) {
bool ff=1;
int ttt=a[3]-a[2];
for(int i=3;i<=n;i++) {
if(a[i]-a[i-1]!=ttt) {
ff=0;
break;
}
}
if(ff&&a[2]-a[1]!=ttt) {
puts("Yes");
return 0;
}
x1[1]=a[1];
for(int i=2;i<=n;i++)
x1[i]=a[1];
for(int i=1;i<=n;i++) {
if(x1[i]==a[i]) {
tot++;
vis[i]=1;
}
}
if(tot==n)
continue;
int pos=1;
while(vis[pos++]);
for(int i=1;i<=n;i++)
x2[i]=a[pos];
for(int i=1;i<=n;i++) {
if(vis[i])
continue;
if(x2[i]==a[i]) {
tot++;
vis[i]=1;
}
}
if(tot==n) {
puts("Yes");
return 0;
}
}
else {
int g=gcd(abs(tmpx),abs(tmpy));
tmpx/=g;
tmpy/=g;
x1[1]=a[1];
for(int i=1+tmpx;i<=n;i+=tmpx)
x1[i]=x1[i-tmpx]+tmpy;
for(int i=1;i<=n;i++) {
if(x1[i]==a[i]) {
tot++;
vis[i]=1;
}
}
if(tot==n)
continue;
int pos=1;
while(vis[pos])
pos++;
x2[pos]=a[pos];
for(int i=pos+tmpx;i<=n;i+=tmpx)
x2[i]=x2[i-tmpx]+tmpy;
for(int i=1;i<=n;i++) {
if(vis[i])
continue;
if(x2[i]==a[i]) {
tot++;
vis[i]=1;
}
}
if(tot==n) {
puts("Yes");
return 0;
}
}
}
puts("No");
return 0;
}
C. From Y to Y
题意:一个字符串的计算价值的方式是:一开始字符串是每个字符一组,然后每次合并两个字符组,合并一个字符组的价值是:
∑c∈{′a′,′b′,′c′,...,′z′}f(S,c)⋅f(T,c) 。这里 S,T 是选择的两个字符组, f(S,c) 表示的是字符组 S 中,出现c 这个字符的次数。我们知道计算方式是多重的,我们现在取总值最小的那个方法。现在给你一个最小价值 k ,让你构造一个不超过1e5 长度的字符串。
思路&&题解:可以通过观察发现,如果一个字符串中有 x 个a 的话,那么对应这些字符 a 贡献的价值是:(x∗(x−1))/2 ,所以只要暴力一下就行了(详情请见代码..)
代码如下:
#include<bits/stdc++.h>
using namespace std;
int k,pre[10001],num[26],pos;
void init() {
pre[0]=pre[1]=0;
for(int i=2;i<=9999;i++)
pre[i]=i*(i-1)/2;
}
int main() {
ios::sync_with_stdio(false);
cin>>k;
init();
if(k==0) {
puts("a");
return 0;
}
for(int i=0;i<26;i++) {
if(k==0) {
for(int x=0;x<26;x++) {
if(!num[x])
continue;
for(int j=1;j<=num[x];j++)
cout<<char('a'+x);
}
cout<<endl;
return 0;
}
pos=lower_bound(pre,pre+10000,k+1)-pre-1;
num[i]=pos;
k=k-pre[pos];
}
return 0;
}