11.3 NOIP模拟赛 (afternoon)

本文提供了三道算法竞赛题目的解答思路及代码实现,包括字符串匹配、素数筛法及图论最短路径问题。通过高效的算法设计,解决了特定场景下的问题。

这里写图片描述

思路:

ans.Len=lngn 取上整
枚举所有的串 存起来排序
然后挨着试2333333
二进制hash 每个串用一个数表示
然后就比较好搞了

代码:

#include<cstdio>
unsigned int v[66000],p,z,i,l,n;char c;
int main(){
    for(l=1;l;l++){
        for(p=0;p<=65536;p++)v[p]=0;
        freopen("ab.in","r",stdin);
        for(p=0,z=(1u<<l)-1,c=getchar();c>32;c=getchar(),++n){
            p=((p<<1)|(c=='B'))&z;if(n+1>=l)v[p/32]|=1u<<(p%32);
        }
        for(p=0;p<(1<<l);p++)if(!(v[p/32]>>(p%32)&1)){
          freopen("ab.out","w",stdout);
            for(i=l;i;i--)
              putchar('A'+(p>>(i-1)&1));
                return putchar('\n'),0;
        }
    }
}

这里写图片描述

思路:

这里写图片描述

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5000000;
bool pd[N+1];int p[N+1],c[N+1];
int maxc(int x){
    if(x<=N)return c[x];
    int ans=x;
    for(int i=1;p[i]*p[i]<=x;i++)
    if(x%p[i]==0){while(x%p[i]==0)x/=p[i];ans=p[i];}
    return max(ans,x);
}
int get(int x,int y,int b){
    if(x>y)return 0;
    if(b==0)return x==1;
    if(y<=p[b])return y-x+1;
    if(x==y)return maxc(x)<=p[b];
    return get(x,y,b-1)+get((x-1)/p[b]+1,y/p[b],b);
}
int main(){
    freopen("prime.in","r",stdin);freopen("prime.out","w",stdout);
    int n,m,b;
    scanf("%d%d%d",&b,&n,&m);
    c[1]=1;
    for(int i=2;i<=N;i++){
        if(!pd[i])p[++p[0]]=i,c[i]=i;
        for(int j=1,t;(t=p[j]*i)<=N;j++){
            pd[t]=1;c[t]=max(c[i],p[j]);if(i%p[j]==0)break;
        }
    }
    printf("%d\n",m-n+1-get(n,m,upper_bound(p+1,p+1+p[0],b)-p-1));
    return 0;
}

这里写图片描述
这里写图片描述

思路:

这里写图片描述

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define rep(i,x,y) for(i=x;i<=y;i++)
#define _rep(i,x,y) for(i=x;i>=y;i--)
#define mp make_pair
#define fi first
#define se second
    inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;}
    template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;};
    template<class T> inline void read(T&x,T&y){read(x);read(y);}
const int N=200010;
const int Q=1000010;
int t,q,n,m,x,y,z,i,j,k,p,ti,d1,d2,cnt;char c;
int ki[Q],q0[Q],q1[Q];
int edge,e[N],b[N],w[N],fir[N],dfn[N],d[N],r[N],h[N],lg2[N],p1[N],p2[N],l[N];pair<int,int> H[N][18];
void add(int x,int y,int z){e[++edge]=y;w[edge]=z;b[edge]=fir[x];fir[x]=edge;}
void dfs(int i){
    h[++z]=i;r[i]=z;
    for(int k=fir[i];k;k=b[k])
    d[e[k]]=d[i]+w[k],dfs(e[k]),h[++z]=i;
}
int getd(int x,int y){
    if(r[x]>r[y])swap(x,y);
    #define u lg2[r[y]-r[x]+1]
    return d[x]+d[y]-2*d[min(H[r[x]][u],H[r[y]-(1<<u)+1][u]).se];
}
int main(){
    freopen("factory2.in","r",stdin);freopen("factory2.out","w",stdout);
    read(t);
    rep(i,1,t){
        c=getc();
        if(c=='R'){read(x,y);++n;if(x)add(x,n,y);}
        else if(c=='C')++m;
        else{++q;read(q0[q],q1[q]);ki[q]=(c=='A');}
    }
    dfs(1);
    rep(i,2,(n<<1))lg2[i]=lg2[i/2]+1;
    _rep(i,(n<<1),1){
        H[i][0]=mp(r[h[i]],h[i]);
        for(int j=1;i+(1<<j)-1<=(n<<1);j++)
        H[i][j]=min(H[i][j-1],H[i+(1<<(j-1))][j-1]);
    }
    rep(i,1,q)
    if(ki[i])
        printf("%d\n",max(max(getd(p1[q0[i]],p1[q1[i]]),getd(p1[q0[i]],p2[q1[i]])),
                          max(getd(p2[q0[i]],p1[q1[i]]),getd(p2[q0[i]],p2[q1[i]]))));
    else{
        x=q0[i];y=q1[i];
        if(!p1[x])p1[x]=p2[x]=y;
        else{
            d1=getd(p1[x],y);d2=getd(p2[x],y);
            if(d1<d2)swap(d1,d2),swap(p1[x],p2[x]);
            if(d1>l[x])l[x]=d1,p2[x]=y;
        }
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值