省选模拟25
今天这个出奇的简单,于是我250分,第一又AK了
第一题,考场上看了一眼就知道是后缀自动机,然而空间不够用了
第二题,一眼切了,直接线段树维护矩阵乘
第三题,只会一个的做法,还有一点点结论没有观察出来...
T1 前缀
前缀,前缀,KMP不就是找最长border的??直接把每一个前缀的border个数加起来就是答案了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e7+5;
char a[N];
int n,nxt[N],sum[N];
ll ans;
signed main(){
freopen("pre.in","r",stdin);
freopen("pre.out","w",stdout);
// cerr<<(sizeof(sam)>>20)<<endl;
scanf("%s",a+1);n=strlen(a+1);sum[1]=ans=1;
for(int i=2,j=0;i<=n;i++){
while(a[i]!=a[j+1]&&j)j=nxt[j];
if(a[i]==a[j+1])j++;nxt[i]=j;
sum[i]=sum[j]+1;ans+=sum[i];
//cerr<<sum[i]<<endl;
}
printf("%lld",ans);
return 0;
}
T2 斐波那契
好用的矩阵乘...
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e5+5;
const int mod=1004535809;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
struct matrix{
int x[2][2];
matrix(){memset(x,0,sizeof(x));}
matrix operator + (matrix a)const{
matrix ret;
fo(i,0,1)fo(j,0,1)ret.x[i][j]=(x[i][j]+a.x[i][j])%mod;
return ret;
}
matrix operator * (matrix a)const{
matrix ret;
fo(i,0,1)fo(k,0,1)if(x[i][k])fo(j,0,1)ret.x[i][j]=(ret.x[i][j]+x[i][k]*a.x[k][j])%mod;
return ret;
}
bool operator == (matrix a)const{
fo(i,0,1)fo(j,0,1)if(x[i][j]!=a.x[i][j])return false;
return true;
}
bool operator !=(matrix a)const{
return !(*this==a);
}
void print(){
fo(i,0,1){
fo(j,0,1)printf("%lld ",x[i][j]);
printf("\n");
}printf("\n");
}
}xs,oe,now;
matrix mksm(matrix x,int y){
matrix ret;
fo(i,0,1)ret.x[i][i]=1;
while(y){
if(y&1)ret=ret*x;
x=x*x;y>>=1;
}return ret;
}
int n,m,a[N];
struct XDS{
#define ls x<<1
#define rs x<<1|1
matrix sum[N*4],tag[N*4];
void pushup(int x){
sum[x]=sum[ls]+sum[rs];
return ;
}
void pushdown(int x){
sum[ls]=sum[ls]*tag[x];
tag[ls]=tag[ls]*tag[x];
sum[rs]=sum[rs]*tag[x];
tag[rs]=tag[rs]*tag[x];
tag[x]=oe;
}
void build(int x,int l,int r){
tag[x]=oe;
if(l==r){
sum[x]=mksm(xs,a[l]-1);
return ;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(x);return ;
}
void ins(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
sum[x]=sum[x]*now;
tag[x]=tag[x]*now;
return ;
}
int mid=l+r>>1;if(tag[x]!=oe)pushdown(x);
if(ql<=mid)ins(ls,l,mid,ql,qr,v);
if(qr>mid)ins(rs,mid+1,r,ql,qr,v);
pushup(x);return ;
}
int query(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return sum[x].x[0][0];
int mid=l+r>>1,ret=0;if(tag[x]!=oe)pushdown(x);
if(ql<=mid)ret=(ret+query(ls,l,mid,ql,qr))%mod;
if(qr>mid)ret=(ret+query(rs,mid+1,r,ql,qr))%mod;
pushup(x);return ret;
}
#undef ls
#undef rs
}xds;
signed main(){
freopen("fib.in","r",stdin);
freopen("fib.out","w",stdout);
xs.x[0][0]=xs.x[0][1]=xs.x[1][0]=1;
oe.x[0][0]=oe.x[1][1]=1;
n=read();m=read();
fo(i,1,n)a[i]=read();
xds.build(1,1,n);
while(m--){
int tp=read(),l=read(),r=read(),x;
if(tp==1){
x=read();now=mksm(xs,x);
xds.ins(1,1,n,l,r,x);
}
else {
printf("%lld\n",xds.query(1,1,n,l,r));
}
}
return 0;
}
T3 过路费
枚举最小的计入贡献的是那条边,然后把所有边的权值都减去这条边的权值
最后加上一个k*这条边的权值
可以证明这样的话,对于不合法的情况都会算多!
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1005;
const int M=2005;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m,k,s,t,ans=inf;
struct D{int x,y,w;}d[M];
bool comd(D a,D b){return a.w<b.w;}
struct E{int to,nxt,val;}e[M];
int head[N],rp;
void add_edg(int x,int y,int z){
e[++rp].to=y;e[rp].nxt=head[x];
e[rp].val=z;head[x]=rp;
}
int dis[N];bool vis[N];
struct node{
int x,ds;
bool operator < (node a)const{
return ds>a.ds;
}
};
priority_queue<node> q;
void spfa(int lim){
memset(dis,0x3f,sizeof(dis));
memset(vis,false,sizeof(vis));
dis[s]=0;q.push(node{s,0});
while(!q.empty()){
int x=q.top().x;q.pop();
if(vis[x])continue;vis[x]=true;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(dis[x]+e[i].val>=dis[y])continue;
dis[y]=dis[x]+e[i].val;
q.push(node{y,dis[y]});
}
}
if(lim==1)ans=min(ans,dis[t]);
else ans=min(ans,dis[t]+k*d[lim].w);
}
signed main(){
freopen("fee.in","r",stdin);
freopen("fee.out","w",stdout);
memset(dis,0x3f,sizeof(dis));
n=read();m=read();k=read();s=read();t=read();
fo(i,1,m)d[i].x=read(),d[i].y=read(),d[i].w=read();
if(k==0){printf("0");return 0;}
sort(d+1,d+m+1,comd);
memset(head,0,sizeof(head));rp=0;
fo(j,1,m)add_edg(d[j].x,d[j].y,d[j].w);
spfa(1);
fo(i,2,m-k+1){
memset(head,0,sizeof(head));rp=0;
fo(j,1,i-1)add_edg(d[j].x,d[j].y,0);
fo(j,i,m)add_edg(d[j].x,d[j].y,d[j].w-d[i].w);
spfa(i);
}
printf("%lld",ans);
return 0;
}
QQ:2953174821
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现