• Adore 解题报告


    Adore

    问题描述

    ( ext{w}) 偶然间得到了(1)(DAG)
    这个 (DAG)(m) 层,第(1)层只有(1)个源点,最后(1)层只有(1)个汇点,剩下的每(1)层都有 (k)
    节点。
    现在小( ext{w}) 每次可以取反第 (i(1 < i < m - 1)) 层和第 (i + 1) 层之间的连边。也就是把原本从
    ((i, k_1)) 连到 ((i + 1, k_2)) 的边,变成从 ((i, k_2)) 连到 ((i + 1, k_1))
    请问他有多少种取反的方案,把从源点到汇点的路径数变成偶数条?
    答案对 (998244353) 取模。

    输入格式

    第一行两个整数 (m),(k)
    接下来 (m - 1) 行, 第一行和最后一行有 (k) 个整数 (0)(1),剩下每行有 (k^2) 个整数 (0)(1),第
    ((j - 1) imes k + t) 个整数表示 ((i, j))((i + 1, t)) 有没有边。

    输出格式

    一行一个整数表示答案。

    数据规模与约定

    (20\%) 的数据满足(m le 10,k le 2)
    (40\%) 的数据满足(m le 10^3,k le 2)
    (60\%) 的数据满足(m le10^3,k le 5)
    (100\%) 的数据满足(4 le m le 10^4,k le 10)

    Solution

    如果你读懂了题目,那么应该不是那么难想。

    如何保证偶数条?发现奇偶可以成为状态,于是状压。

    (dp_{i,s})表示第(i)层节点状态为(s)的方案数

    转移也不难,但是我比较傻写了一种(O(mk^22^k))的辣鸡做法,成功只拿了(60pts)

    如果二进制连边就可以做到(O(mk2^k))了,有点轻微卡常还是注意一下。


    Code:

    #include <cstdio>
    const int N=1e4+10;
    const int mod=998244353;
    int g[N][11][11],m,k,dp[N][1<<10],sta,ans;
    int main()
    {
        scanf("%d%d",&m,&k);
        for(int is,j=1;j<=k;j++)
        {
            scanf("%d",&is);
            sta|=is<<j-1;
        }
        dp[2][sta]=1;
        for(int i=2;i<m-1;i++)
        {
            int a[12]={0},b[12]={0};
            for(int is,j=1;j<=k;j++)
                for(int l=1;l<=k;l++)
                {
                    scanf("%d",&is);
                    a[j]|=is<<l-1;
                    b[l]|=is<<j-1;
                }
            for(int s=0;s<1<<k;++s)
                if(dp[i][s])
                {
                    int t0=0,t1=0;
                    for(int l=1;l<=k;l++)
                        if(s>>l-1&1)
                            t0^=a[l],t1^=b[l];
                    (dp[i+1][t0]+=dp[i][s])%=mod;
                    (dp[i+1][t1]+=dp[i][s])%=mod;
                }
        }
        sta=0;
        for(int is,j=1;j<=k;j++)
        {
            scanf("%d",&is);
            sta|=is<<j-1;
        }
        for(int s=0;s<1<<k;s++)
        {
            if(dp[m-1][s])
            {
                int t=0;
                for(int i=1;i<=k;i++)
                    if(s>>i-1&1&&sta>>i-1&1)
                        t^=1;
                if(!t) (ans+=dp[m-1][s])%=mod;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    2018.10.20

  • 相关阅读:
    Javascript函数式编程要掌握的知识点讲解
    任务
    怎么添加项目到SVN上面
    随便写一点最近开发遇到的问题和解决方法 大部分关于laravel和php
    laravel 将数组转化成字符串 再把字符串转化成数组
    laravel 配置了自己的域名以后, localhost 无法访问 404 not found 的解决方法
    实习日记15
    php接收post过来的 json数据 例子
    数据库如何让自增id重置
    C#连接MySQL数据库
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9821766.html
Copyright © 2020-2023  润新知