2017.10.15离线赛总结

来源:互联网 发布:js clear 方法 编辑:程序博客网 时间:2024/05/16 07:25

prime ——3784

思路:筛一筛质数,再将质数的倍数判一下,前缀和维护,然而这样就卡过去了…当然,正解无非就是更强大的筛法——线性筛。然而,老司机(小c)还有一种做法:将一个数除以其最大质因子,再判断商的最大质因子是否为本身这样似乎不用线性筛就更快了…那么我就将二者结合一下。

#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define LL long long#define N 10000005using namespace std;int Q,L,R;int sum[N];int mark[N],p[N],cnt;void Init(){    mark[1]=1;    REP(i,2,N){        if(!mark[i])p[cnt++]=mark[i]=i;        REP(j,0,cnt){            LL x=1ll*p[j]*i;            if(x>=N)break;            mark[x]=p[j];            if(!(i%p[j]))break;        }    }    REP(i,2,N){        int x=i/mark[i];        sum[i]=sum[i-1]+(mark[x]==x);    }} int main(){//  freopen("prime.in","r",stdin);//  freopen("prime.out","w",stdout);    Init();    scanf("%d",&Q);    while(Q--){        scanf("%d%d",&L,&R);        printf("%d\n",sum[R]-sum[L-1]);    }    return 0;} 

room ——3785

思路:bfs,不解释了,太明显了…But今天一开始切分(求稳),结果切着切着分就少了(tm着样例太水了)…However,这里要状压,常数有点大吧

#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define LL long long#define INF 0x3f3f3f3f#define N 10005#define M 10005#define K 15using namespace std;int n,m,k;struct P30{    int d[105][505];    void solve(){        memset(d,INF,sizeof(d));        REP(i,1,m){            int a,b;            scanf("%d%d",&a,&b);            d[a][b]=1;        }        d[1][1]=0;        REP(l,1,n){             REP(i,1,n){                if(i==k)continue;                REP(j,1,n){                    if(i==j || j==k)continue;                    d[i][j]=min(d[i][j],d[i][l]+d[l][j]);                }            }        }        if(d[1][n]==INF)puts("No Solution");        else printf("%d\n",d[1][n]);    }}p30;struct P50{    int d[N];    struct node{        int from,to;    }es[M];    void Bellman(){        memset(d,INF,sizeof(d));        d[1]=0;        while(1){            bool f=0;            REP(i,1,m)if(d[es[i].from]!=INF && d[es[i].to]>d[es[i].from]+1)f=1,d[es[i].to]=d[es[i].from]+1;            if(!f)break;        }    }    void solve(){        REP(i,1,m)scanf("%d%d",&es[i].from,&es[i].to);        Bellman();        if(d[n]==INF)puts("No Solution");        else printf("%d\n",d[n]);    }}p50;struct P100{    int get[N],vis[N][1<<11];    struct edge{        int to,mark;    };    vector<edge>E[M];    struct node{        int step,x,used;    };    queue<node>Q;    void bfs(){        Q.push((node){0,1,get[1]});        while(!Q.empty()){            node now=Q.front();Q.pop();            if(now.x==n){                printf("%d\n",now.step);                exit(0);            }               REP(i,0,E[now.x].size()-1){                edge y=E[now.x][i];                if((now.used|y.mark)!=now.used)continue;                node nxt;                nxt.x=y.to;                nxt.step=now.step+1;                nxt.used=now.used|get[y.to];                if(vis[nxt.x][nxt.used])continue;                vis[nxt.x][nxt.used]=nxt.step;                Q.push(nxt);            }        }    }    void solve(){        REP(i,1,n){            int f;            get[i]=0;            REP(j,0,k-1){                scanf("%d",&f);                if(f)get[i]|=1<<j;            }        }        REP(i,1,m){            int a,b,f;            scanf("%d%d",&a,&b);            edge tmp;            tmp.to=b;            tmp.mark=0;            REP(j,0,k-1){                scanf("%d",&f);                if(f)tmp.mark|=1<<j;            }            E[a].push_back(tmp);        }        bfs();        puts("No Solution");    }}p100;int main(){//  freopen("room.in","r",stdin);//  freopen("room.out","w",stdout);    scanf("%d%d%d",&n,&m,&k);    if(!k && n<=100)p30.solve();    else if(!k && n<=1000)p50.solve();    else p100.solve();    return 0;}

light ——3786

思路:题意简单明了,就是求树上的两条路径的的重复的点,而且这里两点路径分别为a->b,c->b,那就更显然了,求出两两之间的lca分类讨论一下就出来了,这里分类讨论也是出奇的少,总而言之判一下路径是否覆盖——即a与b的lca和b与c的lca相等时,反之…

#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define INF 0x3f3f3f3f#define N 200005#define S 20using namespace std;int n,Q,num;vector<int>E[N];int D[N],fa[S][N];struct PList{    int Dx;    void dfs(int x,int f){        D[x]=D[f]+1;        REP(i,0,E[x].size()-1){            int y=E[x][i];            if(y==f)continue;            dfs(y,x);        }    }    void solve(){        REP(i,1,n)if(E[i].size()<2)Dx=i;        dfs(Dx,0);        REP(i,1,Q){            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            if(D[a]>=D[b] && D[c]>=D[b])printf("%d\n",min(D[a],D[c])-D[b]+1);            else if(D[a]<=D[b] && D[c]<=D[b])printf("%d\n",D[b]-max(D[a],D[c])+1);            else puts("1");        }    }}p_list;struct P100{    void Up(int &x,int step){        DREP(i,S-1,0)if(step&(1<<i))x=fa[i][x];    }     int Lca(int a,int b){        if(D[a]>D[b])swap(a,b);        Up(b,D[b]-D[a]);        if(a==b)return a;        DREP(i,S-1,0)if(fa[i][a]!=fa[i][b])a=fa[i][a],b=fa[i][b];        return fa[0][a];    }    void Init(){        REP(j,1,S-1)                REP(i,1,n)                    fa[j][i]=fa[j-1][fa[j-1][i]];    }    void dfs(int x,int f){        D[x]=D[f]+1;        fa[0][x]=f;        REP(i,0,E[x].size()-1){            int y=E[x][i];            if(y==f)continue;            dfs(y,x);        }     }    void solve(){        dfs(1,0);         Init();        REP(i,1,Q){            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            int lca1=Lca(a,b),lca2=Lca(b,c),lca3=Lca(a,c);            printf("%d\n",lca1==lca2?D[lca3]-2*D[lca1]+D[b]+1:D[b]-max(D[lca1],D[lca2])+1);        }    }}p100;int main(){//  freopen("light.in","r",stdin);//  freopen("light.out","w",stdout);    scanf("%d%d%d",&n,&Q,&num);    REP(i,1,n-1){        int a,b;        scanf("%d%d",&a,&b);        E[a].push_back(b);        E[b].push_back(a);    }    if(num>=11 && num<=13 || num>=17 && num<=18)p_list.solve();    else p100.solve();     return 0;}

小结:今天的题比较水,但是该ak的还是没有,切分还是不熟练吧(暴力敲太快了,cost打成to…)。

原创粉丝点击