2026马蹄杯
MC0584 蒙嘉受赂通关
本题学到了 \(\mathcal{O(n)}\) 内求出本质不同的回文子串以及统计各个字符出现次数
这里使用的是manacher+字符串哈希
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e5+5;
char s[N],s1[N<<1];
int n,p[N<<1],cnt,r,mid,sum[N<<1];
int ddd[N<<1];
struct font{
ll tot;
char ch;
bool operator<(const font& b) const{
return tot==b.tot? ch<b.ch:tot<b.tot;
}
}ans[30];
int num;
int usd[30];
#define ull unsigned long long
const int P=131;
ull hsh[N<<1],pw[N<<1];
unordered_map<ull,bool> mp;
ull calc(int l,int r){
return hsh[r]-pw[ddd[r]-ddd[l-1]]*hsh[l-1];
}
int h(char ch){
if(ch>='a'&&ch<='z')return ch-'a';
return -1;
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>(s+1);
pw[0]=1;
for(int i=1;i<(N<<1);i++)pw[i]=pw[i-1]*P;
n=strlen(s+1);
s1[++cnt]='|';
for(int i=1;i<=n;i++){
s1[++cnt]=s[i];
s1[++cnt]='#';
}
s1[++cnt]=';';
for(int i=1;i<=cnt;i++){
ddd[i]=ddd[i-1];
if(s1[i]=='#')hsh[i]=hsh[i-1];
else {hsh[i]=hsh[i-1]*P+s1[i];ddd[i]++;}
}
for(int i=1;i<=cnt;i++){
if(i<=r)p[i]=min(p[mid*2-i],r-i+1);
if(mp[calc(i-p[i]+1,i+p[i]-1)]==0){
mp[calc(i-p[i]+1,i+p[i]-1)]=1;
sum[i-p[i]+1]++;sum[i+p[i]]--;
}
while(s1[i-p[i]]==s1[i+p[i]]){
p[i]++;
if(mp[calc(i-p[i]+1,i+p[i]-1)]==0){
mp[calc(i-p[i]+1,i+p[i]-1)]=1;
sum[i-p[i]+1]++;sum[i+p[i]]--;
}
}
if(p[i]+i>r)r=i+p[i]-1,mid=i;
}
for(int i=1;i<=cnt;i++){
sum[i]+=sum[i-1];
if(sum[i]){
if(h(s1[i])>=0){
if(!usd[h(s1[i])]){num++;usd[h(s1[i])]=num;ans[num].ch=s1[i];}
ans[usd[h(s1[i])]].tot+=sum[i];
}
}
}
cout<<num<<'\n';
sort(ans+1,ans+1+num);
for(int i=1;i<=num;i++)cout<<ans[i].ch<<' ';
return 0;
}
MC0585 舞阳失色退场
这题主要是怎么在 \(\mathcal{O(n\log n)}\) 的时间分解质因数
分解质因数+最小生成树
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
const int V=1e6+5;
#define ll long long
int n,t,a[N],vis[V],p[N],cnt,lst[V],tot,siz[N];
ll ans;
basic_string<int> Q;
struct edge{
int u,v;
ll w;
bool operator<(const edge& b) const{
return w<b.w;
}
}e[N*100];
edge mke(int u,int v,ll w){
edge a;
a.u=u;a.v=v;a.w=w*(u-v);
return a;
}
int fa[N];
int find(int x){
return fa[x]==x? x:fa[x]=find(fa[x]);
}
void unionn(int x,int y){
x=find(x);y=find(y);
if(siz[x]>siz[y]){siz[x]+=siz[y];fa[y]=x;}
else {siz[y]+=siz[x];fa[x]=y;}
}
void init(){
// vis[1]=1;
for(int i=2;i<=1e6;i++){
if(vis[i]==0){
p[++cnt]=i;vis[i]=i;
}
for(int j=1;j<=cnt&&p[j]*i<=1e6;j++){
vis[i*p[j]]=p[j];
if(i%p[j]==0)break;
}
}
}
signed main(){
scanf("%d",&t);
init();
for(int i=1;i<V;i++)lst[i]=-1;
while(t--){
tot=0;ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){scanf("%d",&a[i]);}
if(n==1){printf("0\n");continue;}
for(int i=1;i<=n;i++){
int o=vis[a[i]],l=a[i];
while(l!=1){
Q+=o;
if(lst[o]!=-1){
e[++tot]=mke(i,lst[o],o);
}
lst[o]=i;
while(l%o==0)l/=o;
o=vis[l];
}
}
for(int i=1;i<=n;i++)fa[i]=i,siz[i]=1;
sort(e+1,e+tot+1);
for(int i=1;i<=tot;i++){
int u=find(e[i].u),v=find(e[i].v);
if(u!=v){
unionn(u,v);
ans=max(ans,e[i].w);
}
}
if(siz[find(1)]!=n)printf("-1\n");
else printf("%lld\n",ans);
for(auto v:Q){lst[v]=-1;}
Q.clear();
}
return 0;
}

浙公网安备 33010602011771号