zoukankan      html  css  js  c++  java
  • 【NOIP2017提高A组模拟10.7】Adore

    题目

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

    状压dp

    考虑用dp,
    因为k<=10,而路径数只分奇偶,那可以用二进制来表示,
    (f_{i,s})第i层的路径数状态位s的方案数。
    根据边转移就可以了,
    但是这样时间复杂度位(O(n2^kk^2))
    考虑优化,读入的每个点连出去的边都可以用二进制来表示,用位运算,这样就变成(O(nk2^k))的了。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    const int maxlongint=2147483647;
    const int mo=998244353;
    const int N=10005;
    using namespace std;
    int f[N][1034];
    int n,m,b[N][12][12],mi[12],fb[N][12][12],bb[N][12],bc[N][12];
    int read(int &n)
    {
        char ch=' ';int q=0,w=1;
        for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
        if(ch=='-')w=-1,ch=getchar();
        for(;ch>='0' && ch<='9';ch=getchar())q=(q<<1)+(q<<3)+ch-'0';n=q*w;return n;
    }
    int main()
    {
    	mi[0]=1;
    	for(int i=1;i<=11;i++) mi[i]=mi[i-1]*2;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++) read(b[1][1][i]),bb[1][1]+=b[1][1][i]*mi[i-1];
    	for(int i=2;i<=n-2;i++) 
    		for(int j=1;j<=m;j++)
    			for(int k=1;k<=m;k++) read(b[i][j][k]),fb[i][k][j]=b[i][j][k],bb[i][j]+=b[i][j][k]*mi[k-1],bc[i][k]+=fb[i][k][j]*mi[j-1];
    	for(int i=1;i<=m;i++) read(b[n-1][i][1]),bb[n-1][i]+=b[n-1][i][1];
    	f[1][1]=1;
    	for(int i=1;i<=n-1;i++)
    		for(int j=0;j<=mi[m]-1;j++)
    		{
    			int t=f[i][j];
    			if(t)
    			{
    				int tt=0;
    				for(int k=1;k<=m;k++)
    					tt^=bb[i][k]*bool(mi[k-1]&j);
    				f[i+1][tt]=(1ll*f[i+1][tt]+t)%mo;
    				if(i==1 || i==n-1) continue;
    				tt=0;
    				for(int k=1;k<=m;k++)
    					tt^=bc[i][k]*bool(mi[k-1]&j);
    				f[i+1][tt]=(1ll*f[i+1][tt]+t)%mo;
    			}
    		}
    	printf("%lld",f[n][0]);
    }
    
  • 相关阅读:
    linux tar详解
    兼容ie和firefox的日期函数获取两个日期相差的天数
    把Response.Redirect放到TryCatch中出的错误
    如何把string类型转为enum类型

    string.Format的大括号处理
    全国默哀三分钟
    网页快捷键上下翻页(兼容firefox和ie)
    通过免费手机短信来控制电脑“执行者”介绍
    刚刚发现了一个好玩的关于有道的
  • 原文地址:https://www.cnblogs.com/chen1352/p/9079626.html
Copyright © 2011-2022 走看看