23.10.12 div3 CF 总结

最坐牢的一次div3啊QAQ

A:

给定长度为 n 的字符串 x 和长度为 m (n⋅m≤25) 的字符串 s(由小写拉丁字母组成),您可以对字符串 x 应用任意数量的运算。

在一项操作中,您将 x 的当前值附加到字符串 x 的末尾。请注意,此后 x 的值将会改变。

例如,如果x=“aba”,则应用操作后,x将更改为:“aba”→→“abaaba”→→“abaabaabaaba”。

经过多少次最少操作后,s 将作为子字符串出现在 x 中?字符串的子字符串被定义为它的连续段。

输入

输入的第一行包含一个整数 t (1≤t≤1e4) - 测试用例的数量。

每个测试用例的第一行包含两个数字 n 和 m (1≤n⋅m≤25) - 分别是字符串 x 和 s 的长度。

每个测试用例的第二行包含长度为 n 的字符串 x。

每个测试用例的第三行包含长度为 m 的字符串 s。

输出

对于每个测试用例,输出一个数字 - 最小 操作数,之后 s 将作为子字符串出现在 x 中。如果不可能,则输出 −1。

这道题其实就是复制字符串a再拼接,直接再寻找b就行了

然后我就写出了这么一串:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

void init()
{

}

void solve()
{
    int x, y; cin >> x >> y;
    string a, b; cin >> a >> b;
    int n = 0;
    int flag = 0;
    for(int i = 0; i < y; ++i)
    {
        
        if(a.find(b) < a.size())
        {
            flag = 1;
            break;
        }
        ++n;
        a += a;
    }
    if(flag) cout << n << '\n';
    else cout << -1 << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

信心满满交上去之后

TLE

因为当最后结果为-1且b的长度很大的时候,循环次数会多,查找运行的时间也会多。

解决这个问题的方法很简单,a + a多出来的无非就是头尾相接的部分,所以当a的长度大于等于b的长度时,此时只要再复制一次a,如果还没找到,那最后结果肯定就是-1。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

void init()
{

}

void solve()
{
    int x, y; cin >> x >> y;
    string a, b; cin >> a >> b;
    int n = 0;
    int flag = x + y;
    int flag2 = 0;
    for(int i = 0; i < y; ++i)
    {
        
        if(a.find(b) < a.size())
        {
            flag2 = 1;
            break;
        }
        ++n;
        if(!(--flag)) break;
        if(a.size() > b.size())flag = 1;
        a += a;
    }
    if(flag2) cout << n << '\n';
    else cout << -1 << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

但是赛后又发现了这么一个神奇的解法,就是不从这个点出发,直接优化循环次数也是OK的,这个时候就要注意一下数据的大小了,因为字符串长度最多是25,而从a的长度是1,b长度是25的这种最坏情况考虑,就不难发现其实只要循环5次,就一定能满足上面提到的调节,从而找到答案。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

string a, b;

void init()
{

}

void solve()
{
    int n, m;
    string x, s;
    int ans = 0, a = 0, b = 0;
    cin >> n >> m;
    cin >> x;
    cin >> s;
    for(int i = 0; i <= 5; ++i)
    {
        if(x.find(s) != -1)
        {
            cout << ans << '\n';
            return;
        }
        x += x;
        ans++;
    }
    cout << "-1" << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

B:

从前,酒保德西姆发现了三根细线和一把剪刀。

在一次操作中,Decim 选择任意一个 threadlet,并将其切割成两个 threadlet,其长度为正整数,并且它们的总和等于被切割的 threadlet 的长度。

例如,他可以将长度为 55 的细丝切割为长度为 2 和 3 的细丝,但不能将其切割为长度为 2.5 和 2.5 的细丝,或者长度为 0 和 5 的细丝。 },或长度3和4。

Decim 最多可以执行三个运算。他被允许切割先前切割得到的细线。他能把所有的细线都制成相同长度吗?

输入

第一行包含一个整数 t (1≤t≤1e4) - 测试用例的数量。然后是每个测试用例的描述。

在每个测试用例的一行中,有三个整数 a、b、c (1≤a,b,c≤1e9) - 线程的长度。

输出

对于每个测试用例,如果可以通过执行最多三个操作使所有线程长度相等,则输出“YES”,否则输出“NO”。

您可以在任何情况下输出“YES”和“NO”(例如,字符串“yEs”、“yes”、“Yes”和“YES”将被识别为肯定答案)。

我的想法是这样的:

既然有三段且只有三次切的机会,那么肯定就切不到最小值,从这个角度出发,不难得知,另外两端的长度只能是最小值的2倍,3倍或者4倍,且倍数之和绝对不会超过5;

所以我的代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

int a[3];

void init()
{
    
}

void solve()
{
    int min = 1e9 + 9;
    for(int i = 0; i < 3; ++i)
    {
        cin >> a[i];
        if(min > a[i])
        {
            min = a[i];
        }
    }
    int n = 0;
    for(int i = 0; i < 3; ++i)
    {
        if(a[i] % min == 0 && a[i] / min != 1) n += a[i] / min;
        else if(a[i] % min != 0) n = 6;
    }
    if(n <= 5) cout << "YES" << '\n';
    else cout << "NO" << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

但是这样漏考虑了单个数倍数为最小值5倍的情况,导致WA了。

所以还需要特判一下。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

int a[3];

void init()
{
    
}

void solve()
{
    int min = 1e9 + 9;
    for(int i = 0; i < 3; ++i)
    {
        cin >> a[i];
        if(min > a[i])
        {
            min = a[i];
        }
    }
    int n = 0;
    for(int i = 0; i < 3; ++i)
    {
        if(a[i] / min > 4) n = 6;
        if(a[i] % min == 0 && a[i] / min != 1) n += a[i] / min;
        else if(a[i] % min != 0) n = 6;
    }
    if(n <= 5) cout << "YES" << '\n';
    else cout << "NO" << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

当然还有一种方法可以解,且不容易漏细节。

就是可以从三个数的最大公因数出发,每段长度除以最大公约数再减1就是减该段用的次数,再相加,判断是否小于等于3就可得到该题解。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

ll a[3];

void init()
{
    
}

void solve()
{
    for(int i = 0; i < 3; ++i) cin >> a[i];
    ll g, s = 0;
    int n = 0;
    g = __gcd(a[0], a[1]);
    g = __gcd(g, a[2]);
    for(int i = 0; i < 3; ++i)
    {
        if(a[i] / g > 1)
        {
            s += a[i] / g;
            n++;
        }
    }
    if(s - n <= 3)cout << "YES" << '\n';
    else cout << "NO" << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

最长的一篇~

属实是坐牢坐的印象深刻。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值