Codeforces Round #370 (Div. 2)

A题:


题意:


有数组a[i] (2<=i<100000),且a[i] = b[i] - b[i+1] + b[i+2] - b[i+3]...(假如n == 3 ,a[1] = b[1] - b[2] + b[3]; a[2] = b[2] - b[3]; a[3] = b[3])

现在给出n与数组a[i],求数组b[i]


题解:


手写求出b[n] = a[n],b[n-1] = a[n-1] + b[n]; b[n-2] = a[n-2] + b[n-1] - b[n]; b[n-3] = a[n-3] + b[n-2] - b[n-1] + b[n]...

根据这些可以推断出b[i] = a[i] + b[i+1] - (b[i+1] - a[i+1])(1<=i<n),然后就可以求解数组b了。


#include<iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
using namespace std;
#define MAX_N 100005
#define inf 0x7fffffff
#define LL long long
#define ull unsigned long long
#define mod 10007
LL INF=9e18;

LL a[MAX_N];
LL b[MAX_N];
int main()
{
    int n;
    cin >> n;
    for(int i=1;i<=n;i++) {
        cin >> a[i];
    }
    b[n] = a[n];
    for(int i=n-1;i>0;i--) {
        b[i] = a[i] + b[i+1] - (b[i+1] - a[i+1]);
    }
    for(int i=1;i<=n;i++) {
        printf("%lld%c",b[i],i==n?'\n':' ');
    }
}

B题:


题意:


给出字符串s(1<=|s|<=100000),s中仅包括‘L’,‘R’,‘U’,‘D’,分别表示左,右,上,下,问从原点出发,能否回到原点,

如果不能那最少修改几个字符能够回到原点,如果如何修改都无法回到原点则输出-1.


题解:


当|s|为奇数时无论如何修改都无法回到原点,所以直接输出-1

当|s|为偶数时,设x, y为最后的坐标,当x,y都不为0时可以通过改变一个字符的值使两个坐标都向0靠近,比如x=y=1时,

只用将一个'U'变成‘L’就可以了,所以先将x,y中绝对值小的那个先变成0,剩下的那个一定为偶数,所以修改次数再加上(abs(x)-abs(y))/2就可以了


#include<iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
using namespace std;
#define MAX_N 100005
#define inf 0x7fffffff
#define LL long long
#define ull unsigned long long
#define mod 10007
LL INF=9e18;

char s[MAX_N];
int main()
{
    int x, y;
    x = y = 0;
    scanf("%s",s);
    int len = strlen(s);
    if(len & 1) {
        cout << -1 << endl;
        return 0;
    }
    for(int i=0;i<len;i++) {
        char c = s[i];
        if(c == 'U') y++;
        else if(c == 'D') y--;
        else if(c == 'L') x--;
        else if(c == 'R') x++;
    }
    x = abs(x);
    y = abs(y);
    int ans;
    if(x && y) {
        ans = min(x, y);
        x -= ans;
        y -= ans;
        ans += (max(x, y) / 2);
    }
    else {
        if(!x)
            swap(x, y);
        ans = x / 2;
    }
    printf("%d\n",ans);
}


C题:


题意:

给你一个边长为x的等边三角形,问最少经过几次变换能变成一个边长为x的等边三角形(3<=y<x<=100000),每次只能对一条边进行改变且必须保证改变后三边仍能组成三角形,比如x = 8,y = 5 可以经过3次改变:(8,8,8)->(8,8,5)->(8,5,5)->(5,5,5)


题解:


可以将题目视为边长为y的等边三角形最少经过几次变换能够变成边长为x的等边三角形,这样只要保证每次的边变换都是最大的变换就能保证变换次数最少了,

手写推出第k次边变换后最长那条边为 f[k] - f[k] - 1 如果第k次变换后的最长边>=x则再将剩下两边变成x即可得到答案为k+2

概是这样变的:(y,y,y)->(2y-1,y,y)->(2y-1,3y-2,y)->(2y-1,3y-2,5y-4)...->(x,x,x)


#include<iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
using namespace std;
#define MAX_N 100005
#define inf 0x7fffffff
#define LL long long
#define ull unsigned long long
#define mod 10007
LL INF=9e18;

int f[35];
int main()
{
    f[0] = 1;
    f[1] = 2;
    for(int i=2;i<=30;i++) {
        f[i] = f[i-1] + f[i-2];
    }
    int x,y;
    cin >> x >> y;
    int ans;
    for(int i=1;i<=30;i++) {
        if(f[i]*y-f[i]+1>=x) {
            ans = i;
            ans += 2;
            break;
        }
    }
    cout << ans << endl;
}

总结:


B题没测试几组数据直接就提交了,交完就有点虚了,最后果然错了。

A、B两题花了30min就好了,C题最后40s的时候提交才过,第一次这么赶,不过还好过了,一开始看第三组样例的时候我就在想是不是第一条边的改变是有规律的,然后就一直陷入找规律中,后来只有13min的时候提交了一发错了,感觉找不到啥规律,于是逆向的想了一下,突然就想到了可以从y到x,然后手推了一下,貌似还不错,就直接敲了然后在最后40s的时候已提交过了,那个时候的心情真是好啊~~~这次C题也给了我启发,正向不行就逆向思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值