• 平时二十五测


    今天又文件错误了一道A的题,真是不长教训;

    题解:

    第一题:

    每一层 k很小,考虑对路径数的奇偶性状压。
    令 dp[i][S]表示第i 层奇偶状态为 S 的方案数,由于连边是固定的,转移显然。
    注意到 O(k^2)转移需要优化成 O(k),可以先把每一个点及与之相连的点对应的状态先 DP 出来,用位运算做到对每一个点 O(1) 转移,从而总的是 O(k)

    我开始想到了这个做法,但觉得搞路径太麻烦,就放弃了,后来向轩哥学习了一波;

    把前后两个状态压成二进制,在并起来就好了;因为只有后面是奇数并且边联通才有贡献,其他情况没有贡献,并起来是0;

    用记搜跑起来挺快的;

    #include<bits/stdc++.h>
    using namespace std;
    const long long mod=998244353;
    int fg[10005][11], g[10005][11], n, a[1005], bin[(1<<10)+1], dp[10005][(1<<10)+1], pre, ed, k;
    #define RG register
    int ksm(long long a,int b){
        long long ret=1;
        for(;b;b>>=1,a=a*a%mod)
        if(b&1)ret=ret*a%mod;
        return (int)ret;
    }
    
    int dfs(int now, int sta){
        if(now==2){
            return ( (bin[sta&pre]&1) == 0 );
        }
        if(dp[now][sta] != -1) return dp[now][sta];
        if(sta == 0){
            return dp[now][sta] = ksm(2, now-2);
        }
        int ret=0,tmp=0;
        for(RG int i=0;i<k;i++){
            tmp=(tmp + ((bin[sta&g[now-1][i]]&1)<<i) );
        }
        ret+=dfs(now-1,tmp);
        tmp=0;
        for(RG int i=0;i<k;i++){
            tmp=(tmp+ ((bin[sta&fg[now-1][i]]&1)<<i) );
        }
        ret+=dfs(now-1,tmp);
        if(ret>=mod)ret-=mod;
        return dp[now][sta]=ret;
    }
    
    
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int main(){
        freopen("adore.in","r",stdin);
        freopen("adore.out","w",stdout);
        scanf("%d%d",&n,&k);
        int x;
        memset(dp, -1, sizeof(dp));
        for(int s=1;s<(1<<k);s++)bin[s]=bin[s>>1]+(s&1);
        for(int i=0;i<k;i++){
            x = read();
            if(x)pre += (1<<i);
        } 
        for(int i=2;i<n-1;i++){
            for(int j=0;j<k*k;j++)a[j] = read();
            for(int j=0;j<k;j++)
                for(int t=0;t<k;t++){
                    g[i][j] += (a[j*k+t]<<t);
                    fg[i][j] += (a[t*k+j]<<t);
                }
        }
        for(int i=0;i<k;i++){
            x = read();
            if(x) ed += (1<<i);
        }
        int ans = dfs(n-1, ed);
        printf("%d
    ",ans);
    }
    View Code

    第二题:这题暴力搞就可以了,又froepen了;

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 10000005;
    char s[6005][2005];
    int n, lim, res, cnt[6005], k, bin[(1<<6) + 1];
    
    bool uni(int x, int y){
        int now=0;
        for(int i=0;i<lim;i++){
            int t=(s[x][i]-33)&(s[y][i]-33);
            now+=bin[t];
            if(now>=(n>>1))return 1;
        }
        if(res){
            int t=(s[x][lim]-33)&(s[y][lim]-33);
            for(int j=5,p=1;p<=res;p++,j--)
                if(t&(1<<j))now++;
        }
        
        return now>=(n>>1);
        
    
    }
    inline int up(int x){
        int tot=0;
        for(int i=0;i<k;i++)
            tot+=bin[s[x][i]-33];
        return tot;
    }
    inline int go(int s){return s ? go(s>>1) + (s&1) : 0;}
    
    int main(){
        freopen("confess.in","r",stdin);
        freopen("confess.out","w",stdout);
        int fg = 0, a1, a2;
        scanf("%d", &n);
        scanf("%s", s[1]);
        
        k = strlen(s[1]);
        lim = n*2/6, res=n*2%6;
        
        for(int i=0;i<(1<<6);i++)bin[i]=go(i);
        cnt[1]=up(1);
        
        
        for(int i = 2; i <= n+1; i++){
            scanf("%s", s[i]);
            if(fg)continue;
            cnt[i]=up(i);
            if(cnt[i]<(n>>1)) continue;
            for(int j = 1; j < i; j++){
                if(cnt[j]>=(n>>1) && uni(i, j)) {a1=j, a2=i; fg = 1;break;}
            }
            
        }
        fg ? printf("%d %d
    ", a1, a2) : printf("NO Solution
    ");
    }
    View Code

    第三题:贪心,考虑之前将军令的做法,从度数最深的跳k级father,再将father管辖的儿子放入优先队列,把当时同一层的儿子覆盖,如果s还有剩余,就覆盖上一层的儿子(这一层的儿子本来可以是更上面的节点管);

    就这样一直做下去就好了;

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ex(i, u) for(register int i = h[u]; i; i = G[i].nxt)
    const int M = 1e5 + 5;
    int h[M], fg, tot, n, k, s, dep[M], anc[M][7], vis[M], id[M], que[M];
    struct edge{int v, nxt;}G[M<<1];
    void add(int u, int v){G[++tot].v = v, G[tot].nxt = h[u], h[u] = tot;}
    
    inline bool cmp(int a, int b){return dep[a]>dep[b];}
    void dfs(int u, int faa){
        anc[u][0]=faa;
        for(int p=1;p<=5;p++)
            anc[u][p]=anc[anc[u][p-1]][p-1];
        dep[u]=dep[faa]+1;
        ex(i, u){
            int v=G[i].v;
            if(v==faa)continue;
            dfs(v, u);
        }
    }
    
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    #define RG register
    int cnt;
    inline void col(int u,int f, int now){
        if(now > k) return ;
        que[++cnt]=u;
        ex(i, u){
            int v=G[i].v;
            if(v==f||vis[v]) continue;
            col(v, u, now+1);
        }
        
    } 
    
    int main(){
        freopen("repulsed.in","r",stdin);
        freopen("repulsed.out","w",stdout);
        n = read(), s = read(), k = read(); 
        for(RG int i = 1; i < n; i++){
            int u = read(), v = read();
            add(u, v); add(v, u);
        }
        if(s == 1) {
            printf("%d
    ", n); return 0;
        }
        else {
            int ans=0,vor=0;
            dfs(1, 0);
            for(RG int i=1;i<=n;i++)id[i]=i;
            sort(id+1, id+1+n, cmp);
            
            
            for(RG int i=1;i<=n;i++){
                RG int u=id[i], dd=dep[id[i]];
                if(vis[u])continue;
                int tp=k;
                for(RG int p=0;tp;p++,tp>>=1)
                    if((tp&1) && anc[u][p]) u=anc[u][p];
                cnt=0;
                col(u, 0, 0);
                sort(que+1, que+1+cnt, cmp);
                RG int j;
                for(j=1;j<=cnt&&dep[que[j]]==dd;j++){
                    vis[que[j]]=1;
                }
                int tmp=(j+s-2)/s;
                RG int res=tmp*s-(j-1);
                ans+=tmp;
                for(j;res;res--,j++)vis[que[j]]=1;
                //for(int j=1;j<=n;j++)printf("%d",vis[j]);printf("
    ");
                
            }
            printf("%d
    ",ans);
        }
        
    }
    View Code

     

  • 相关阅读:
    Python 多核 多线程 调度
    mysql-select for update
    Python logging模块
    TCP/IP和HTTP协议与Socket的区别联系
    DNS+CDN
    wget命令
    Cannot find module 'webpack-cli/bin/config-yargs
    TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'
    js 创建私有变量
    报错集锦及解决方案
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9929932.html
Copyright © 2020-2023  润新知