Codeforces Round #431 (Div. 2) 总结

这场…没发挥出实力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 是选择的两个字符组, fS,c 表示的是字符组 S 中,出现c这个字符的次数。我们知道计算方式是多重的,我们现在取总值最小的那个方法。现在给你一个最小价值 k ,让你构造一个不超过1e5长度的字符串。
思路&&题解:可以通过观察发现,如果一个字符串中有 x a的话,那么对应这些字符 a 贡献的价值是:x(x1)/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;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值