2025-11-22

CF

Problem - 550C - Codeforces(数学)

能被8整除的数,后三位一定能被8整除

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2e5+10;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string s;
    cin >> s;
    int a, b, c;
    if(s.find('0')!=-1){
        cout << "YES\n0";
        return 0;
    }
    for (int i = 0; i < s.size();i++){
        a = s[i] - '0';
        for (int j = i + 1; j < s.size();j++){
            b = s[j] - '0';
            for (int k = j + 1; k < s.size();k++){
                c = s[k] - '0';
                if((a*100+b*10+c)%8==0){
                    cout << "YES\n";
                    cout<< a << b << c;
                    return 0;
                }

            }
            if((a*10+b)%8==0){
                cout << "YES\n";
                cout << a << b;
                return 0;
            }
        }
        if(a%8==0){
            cout << "YES\n";
            cout << a << endl;
            return 0;
        }
    }
    cout << "NO\n";
}

Problem - 332B - Codeforces(枚举)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2e5+10;
LL sum[N], a[N], z1, z2, ans,mx[N],pos[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, k;
    cin >> n >> k;
    for (int i = 1; i <= n;i++){
        cin >> a[i];
        sum[i] = sum[i - 1] + a[i];
        if(i>=k)
            sum[i] -= a[i-k];
    }
    for (int i = n; i >= k;i--){
        if(sum[i]>=mx[i+1]){
            pos[i] = i;
            mx[i] = sum[i];
        }else{
            mx[i] = mx[i + 1];
            pos[i] = pos[i + 1];
        }
    }
    for (int i = k; i <= n;i++){
        LL csum = sum[i] + mx[i + k];
        if(ans<csum){
            z1 = i - k + 1;
            z2 = pos[i + k] - k + 1;
            ans = csum;
        }
    }
    cout << z1 << " " << z2 << endl;
}

字符串

Problem - 25E - Codeforces(KMP)(2200虚高)

要会分类讨论

  • 三者无包含关系
  • 有两个字符包含于第一个字符用K[i][j]<0&&k[i][t]<0(这里k[i][t]比k[j][t]好,应该已经判断j被i包含了,所以判断i和t的关系是否包含)
  • 一个字符被前一个字符包含的两种情况i包含j和j包含t
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=1e5+10;
const int INF = 1e9;
int ne[3][N],len[3];
int K[3][3];

void getnext(int m,string s2,int t){
    int j = 0;
    for (int i = 2; i <= m;i++){
        while(j&&s2[i]!=s2[j+1])
            j = ne[t][j];
        if(s2[i]==s2[j+1])
            j++;
        ne[t][i] = j;
    }
}

int KMP(int n,int m,string s1,string s2,int t){
    int j = 0, cnt = 0;
    for (int i = 1; i <= n;i++){
        while(j&&s1[i]!=s2[j+1])
            j = ne[t][j];
        if(s1[i]==s2[j+1])
            j++;
        if(j==m){
            return -1;
        }
    }
    return j;//返回 s1后缀和s2前缀匹配最大值
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string s[3];
    cin >> s[0] >> s[1] >> s[2];
    len[0] = s[0].size(), len[1] = s[1].size(), len[2] = s[2].size();
    s[0] = " " + s[0];
    s[1] = " " + s[1];
    s[2] = " " + s[2];

    for (int i = 0; i < 3;i++){
        getnext(len[i], s[i], i);//算 i子串的 ne数组
        for (int j = 0; j < 3;j++){
            K[j][i] = KMP(len[j], len[i], s[j], s[i], i);
        }
    }
    int ans = INF;
    for (int i = 0; i < 3;i++){
        for (int j = 0; j < 3;j++){
            for (int t = 0; t < 3;t++){
                if(i==j||j==t||i==t)
                    continue;
                int sum = len[i] + len[j] + len[t] - K[i][j] - K[j][t];
                if(K[i][j]>=0&&K[j][t]>=0)//三个都有部分重叠
                    ans = min(ans, sum);
                else{
                    if(K[i][j]<0&&K[i][t]<0){//j和 t都和 i完全重叠
                        ans = min(ans, len[i]);
                    }
                    else if(K[i][j]<0){
                        ans = min(ans, len[i] + len[t] - K[i][t]);
                    }else if(K[j][t]<0){
                        ans = min(ans, len[i] + len[j] - K[i][j]);
                    }
                }
            }
        }
    }
    cout << ans << endl;
}   

P3435 [POI 2006] OKR-Periods of Words - 洛谷(KMP)

题意:求所有前缀的最大周期长度之和,即找每个前缀的最小前后缀相等的长度
由于KMP求的是最长匹配长度,所以用递推找最小,同时更新ne数组,加快效率

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=1e6+10;
int ne[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    LL ans = 0;
    string s;
    cin >> n >> s;
    s = " " + s;
    for (int i = 2, j = 0; i <= n;i++){
        while(j&&s[i]!=s[j+1])
            j = ne[j];
        if(s[i]==s[j+1])
            j++;
        ne[i] = j;
    }
    for (int i = 2, j = 2; i <= n;i++,j=i){
        while(ne[j])
            j = ne[j];//找前缀 i最短匹配的前后缀
        if(ne[i])
            ne[i] = j;//更新 ne[i]
        ans += i - j;
    }
    cout << ans << endl;
}

P2375 [NOI2014] 动物园 - 洛谷(KMP)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 1e9+7;//注意取模数
const int N=1e6+10;
int ne[N],num[N];
// num[i]:对于字符串 S 的前 i 个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠的数量

void solve()
{
    int n;
    string s;
    cin>> s;
    n = s.size();
    s = " " + s;
    num[1] = 1;//初始化

    for (int i = 2, j = 0; i <= n; i++)
    {
        while (j && s[i] != s[j + 1])
            j = ne[j];
        if (s[i] == s[j + 1])
            j++;
        ne[i] = j;
        num[i] = num[j] + 1;//j满足的数量加上j子串本身
    }
    LL ans = 1;
    for (int i = 2, j = 0; i <= n;i++){
        while(j&&s[i]!=s[j+1])
            j = ne[j];
        if(s[i]==s[j+1])
            j++;
        while((j<<1)>i)//把重叠最长前后缀换成不重叠
            j = ne[j];
        ans = ans * (LL)(num[j] + 1) % mod;//依题意
    }
    cout << ans << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {

        solve();
    }
}

碎碎念

今天周六,下周应该是最轻松的一周,但12月份就要开始期末了,要忙着电工学复习,六级还有毛概考试,隔两天一门就离谱。
下周打算学字典树ac自动机,然后洛谷字符串题单刷完,还剩几题
然后就是刷刷cf,补个div3
多花时间给英语六级!

posted @ 2025-11-22 19:36  Seren_blingbling  阅读(4)  评论(0)    收藏  举报