JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore
来源:互联网 发布:嗨氏黑历史知乎 编辑:程序博客网 时间:2024/06/04 18:57
题目
Description
小w 偶然间见到了一个DAG。
这个DAG 有m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k 个节点。
现在小w 每次可以取反第i(1 < i < n - 1) 层和第i + 1 层之间的连边。也就是把原本从(i, k1) 连到(i + 1, k2) 的边,变成从(i, k2) 连到(i + 1, k1)。
请问他有多少种取反的方案,把从源点到汇点的路径数变成偶数条?
答案对998244353 取模。
Input
一行两个整数m, k。
接下来m - 1 行, 第一行和最后一行有k 个整数0 或1,剩下每行有k2 个整数0 或1,第(j- 1)* k + t 个整数表示(i, j) 到(i + 1, t)有没有边。
Output
一行一个整数表示答案。
Sample Input
5 3
1 0 1
0 1 0 1 1 0 0 0 1
0 1 1 1 0 0 0 1 1
0 1 1
Sample Output
4
Data Constraint
100% 的数据满足4 <= m <= 10^4, k <= 10。
题解
这道题很容易看错,是整行路径取反。
我们发现这题的两个亮点。①k≤10,②奇偶性。
所以可以设装压DP。
设
我们知道了第i层不取反的走到下一层的点的对应的方案数的奇偶性。
a0表示不取反,下一行的状态。(a1表取反)
那么
这表示什么意思?
如果第i+1行的某x个二进制位为1,说明到点(i+1,x)方案数为奇数。
走到(i,j)的方案数为奇数,且能够走到第i+1行的点(i+1,x),对走到(i+1,x)的方案数贡献为奇数。否则为偶数。
至于走到(i+1,x)的方案数则为上一行k个点走到(i+1,x)的方案数的总和。
所以二进制数a[i]&s的1的个数的奇偶性就代表走到(i+1,x)的方案数的奇偶性。
第1行和第n-1行要特殊一些,①不能将路径取反,②该行只有1个点。
第1行和第n-1行的转移与第2~n-2行类似。
总结一下
①虽然这是道很多人认为很简单的DP题,但我认为想起来不简单。
②值得推敲的:
每一行的取反/不取反可以通过DP的形式组成了一个个不重不漏的状态。
③即使我知道这是状压DP,但是算方案数的奇偶性还是挺恶心的一件事。
即运算/状态转移方面有很大的问题。
解决方案:利用二进制的巧妙性。
(I)条件的合并:逻辑运算。
(II)奇数偶数加起来的和的奇偶性&二进制数的1的个数的奇偶性相结合。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 10010#define LL long long#define mo 998244353#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;LL _2[15];LL i,j,k,l,n,m,x,o,ans;LL s,a0,a1,a[15],b[15];LL f[N][1030],cnt[1030];int main(){ freopen("adore.in","r",stdin); freopen("adore.out","w",stdout); _2[1]=1;fo(i,2,14)_2[i]=(_2[i-1]*2)%mo; scanf("%lld%lld",&n,&k); s=0; fo(i,1,k){ scanf("%lld",&x); s|=x*_2[i]; } f[0][s]=1;o=0; fo(i,0,_2[k+1]-1)cnt[i]=cnt[i/2]^(i&1); fo(i,2,n-2){ o=1-o; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(f[o],0,sizeof(f[o])); fo(j,1,k)fo(l,1,k){ scanf("%lld",&x); if(x)a[j]|=_2[l],b[l]|=_2[j]; } fo(s,0,_2[k+1]-1) if(f[1-o][s]){ a0=a1=0; fo(j,1,k){ a0|=cnt[s&a[j]]*_2[j]; a1|=cnt[s&b[j]]*_2[j]; } f[o][a0]=(f[o][a0]+f[1-o][s])%mo; f[o][a1]=(f[o][a1]+f[1-o][s])%mo; } } o=1-o; memset(f[o],0,sizeof(f[o])); a[1]=0; fo(i,1,k){ scanf("%lld",&x); a[1]|=x*_2[i]; } fo(s,0,_2[k+1]-1) if(f[1-o][s]){ a0=cnt[s&a[1]]*_2[1]; f[o][a0]=(f[o][a0]+f[1-o][s])%mo; } printf("%lld",f[o][0]); return 0;}
- JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore
- JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore
- 【NOIP2017提高A组模拟10.7】Adore
- 【NOIP2017提高A组模拟10.7】Adore
- jzoj5398. 【NOIP2017提高A组模拟10.7】Adore
- JZOJ5398. 【NOIP2017提高A组模拟10.7】Adore
- JZOJ 5399. 【NOIP2017提高A组模拟10.7】Confess
- 【JZOJ 5400】【NOIP2017提高A组模拟10.7】Repulsed
- JZOJ 5400. 【NOIP2017提高A组模拟10.7】Repulsed
- JZOJ 5400. 【NOIP2017提高A组模拟10.7】Repulsed
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- JZOJ 5195. 【NOIP2017提高组模拟7.3】A
- JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
- JZOJ 100030. 【NOIP2017提高A组模拟7.8】为了爱情
- jzoj. 100031. 【NOIP2017提高A组模拟7.9】外星密码
- JZOJ 100035【NOIP2017提高A组模拟7.10】区间
- JZOJ 100036 【NOIP2017提高A组模拟7.10】随机
- 【超分辨率】FSRCNN--Accelerating the Super-Resolution Convolutional Neural Network
- Miller-Rabin
- Portlet 通信(二) Portlet URL
- Python Re正则表达式
- java-web开发学习路线参考
- JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore
- python 定义类时,内部方法的互相调用
- Java中的匿名内部类总结
- MYSQL SQL_NO_CACHE的真正含义
- POJ1182 食物链(并查集)
- Vim 从放弃到拿起
- 网络通讯
- Java中的四种引用类型分析
- iOS中Crash采集及PLCrashReporter使用