• 20190811 NOIP模拟测试17 「入阵曲 · 将军令 · 星空 」


    T1 入阵曲

      将二维压成一维来做,维护每一列的前缀和,n^2枚举最上一行和最下一行,把中间这几行当成一行来做,维护一个桶记录这几行前几列的和的余数是x的个数,因为在模K意义下余数相同的两个数的差是K的倍数 时间复杂度 O(n^3)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,K,a[410][410],sum[410][410],tmp[1100000],p[1100000];
    inline int read(){
        register int ret;
        register char r;
        while(r=getchar(),r<'0'||r>'9');
        ret=r^48;
        while(r=getchar(),r>='0'&&r<='9') ret=(ret<<1)+(ret<<3)+(r^48);
        return ret;
    }
    int main(){
        n=read(),m=read(),K=read();
        for(register int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=read(),
                sum[i][j]=(sum[i-1][j]+a[i][j])%K;//维护第j列前缀和
        long long ans=0;
        for(register int i=1;i<=n;i++){
            for(register int j=i;j<=n;j++){
                int cet=0;
                for(register int l=1;l<=m;l++){
                    cet=((cet+sum[j][l]-sum[i-1][l])%K+K)%K;
                    ans+=tmp[cet]++;
                    if(cet==0) ans++;
                    if(tmp[cet]==1) p[++p[0]]=cet;
                }
                for(int l=1;l<=p[0];l++) tmp[p[l]]=0;
                p[0]=0;
            }
        }
        printf("%lld
    ",ans);
    }
    View Code

    T2 将军令

      可以想到像 小胖守皇宫 那样的树上DP ,k==1的情况可以做,k==2的情况也可以YY掉,但是K==3或20的情况就不好YY了(但是听说洛谷上有写DP 通式的,码量很小)

      正解是贪心,无根树变有根树,DFS 一遍,用大根堆维护深度最深的点,从该点向上找距他为K的点(如果距离小于K就走到了根,那就用根就行了),然后从这个点在整棵树上找距他小于等于K的点,以后从堆里拿出标记的点直接跳即可。 注意在标记的时候,千万不要碰到一个标记过的点就return,有可能这个点的儿子没有被覆盖,而当前驻扎小队的点会覆盖它的儿子

      PS :这样会TLE 95 ,可以记录如果一个点的所有子孙都被覆盖了(标记过),在开一个数组,把该点标记,这种点是可以跳的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,d,t,tot;
    int to[210000],head[110000],nex[210000],fa[210000],v[210000],al[210000];
    struct node{
        int dep,id;
        bool operator < (node b)const{
            return dep<b.dep;
        }
        node(int a,int b){id=a,dep=b;}
    };
    priority_queue<node>q;
    void add(int x,int y){
        to[++tot]=y,nex[tot]=head[x],head[x]=tot;
    }
    void dfs(int x,int pre,int dis){
        q.push(node(x,dis+1));
        fa[x]=pre;
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(y==pre) continue;
            dfs(y,x,dis+1);
        }
    }
    void work(int x,int k){
        v[x]=1;
        if(nex[head[x]]==0){
            if(to[head[x]]==fa[x]||al[to[head[x]]]) al[x]=1;
        }
        if(k==0) return;
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(al[y]) continue;//避免重复,陷入死循环
            work(y,k-1);//走儿子的同时,也能走到爸爸
        }
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(y==fa[x]) continue;
            al[x]=min(al[y],al[x]);
        }
    }
    int main(){
        scanf("%d%d%d",&n,&d,&t);
        for(int i=1,x,y;i<n;i++){
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,0,0);
        int ans=0;
        while(q.size()){
            int w=q.top().id;
            q.pop();
            if(v[w]) continue;
            for(int i=1;i<=d&&w!=1;i++,w=fa[w]);
            ans++;
            work(w,d);
        }
        printf("%d
    ",ans);
    }
    View Code

    T3 星空

       https://www.luogu.org/problemnew/solution/P3943

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    int n,K,m,num;
    int a[41000],b[70],c[20],v[41000],dis[20][41000],inq[41000],f[1<<17],to[1<<17];
    void Dijistra(){
        memset(dis,0x3f,sizeof(dis));
        queue<int>q;
        for(int w=1;w<=num;w++){
            q.push(c[w]);
            inq[c[w]]=1;
            dis[w][c[w]]=0;
            while(q.size()){
                int x=q.front();
                inq[x]=0;
                q.pop();
                for(int i=1;i<=m;i++){
                    int y=x-b[i];
                    if(y>0&&dis[w][y]>dis[w][x]+1){
                        dis[w][y]=dis[w][x]+1;
                        if(!inq[y]){
                            q.push(y);
                            inq[y]=1;
                        }
                    }
                    y=x+b[i];
                    if(y<=n&&dis[w][y]>dis[w][x]+1){
                        dis[w][y]=dis[w][x]+1;
                        if(!inq[y]){
                            q.push(y);
                            inq[y]=1;
                        }
                    }
                }
            }
        }
    }
    int main(){
        scanf("%d%d%d",&n,&K,&m);
        n++;
        for(int i=1,x;i<=K;i++){
            scanf("%d",&x);
            a[x]^=1,a[x+1]^=1;
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&b[i]);
        }
        for(int i=1;i<=n;i++){
            if(a[i])
                 c[++num]=i;
        }
        Dijistra();
    /*    cout<<num<<endl;
        for(int i=1;i<=num;i++){
            for(int j=1;j<=num;j++){
                printf("%d %d %d
    ",i,j,dis[i][c[j]]);
            }
        }*/
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        for(int i=1;i<=num;i++) to[1<<(i-1)]=i;
        for(int i=0;i<=(1<<num)-1;i++){
            for(int j=i;j;j-=j&(-j)){
                int w=to[j&(-j)],sta=j-(j&(-j));
                for(int l=sta;l;l-=l&(-l)){
                    int ww=to[l&(-l)];
                    f[i]=min(f[i],f[i^(j&(-j))^(l&(-l))]+dis[w][c[ww]]);
                }
            }
        }
        printf("%d
    ",f[(1<<num)-1]);
    }
    View Code

        

  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/heoitys/p/11336760.html
Copyright © 2020-2023  润新知