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
多花时间给英语六级!

浙公网安备 33010602011771号