ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【AT1975】 [ARC058C] 和風いろはちゃん(状压dp)

2022-07-23 08:00:28  阅读:116  来源: 互联网

标签:10 le 后缀 合法 ARC058C include 序列 AT1975 dp


原题链接

题意

若 \(a=\{a_1,a_2,\cdots a_n\}\) 存在 \(1\le x<y<z<w\le n+1\) 满足 \(\sum\limits_{i=x}^{y-1}a_i=X,\sum\limits_{i=y}^{z-1}a_i=Y,\sum\limits_{i=z}^{w-1}a_i=Z\) 时,则称数列 \(a\) 是好的

-求在所有长度为 \(n\) 且 \(a_i\in\mathbb{N}^{+}\cap[1,10]\) 的 \(10^n\) 个序列 \(a\) 中,有多少个序列是好的,答案对 \(10^9+7\) 取模。

数据范围

\(3\le n\le40\),\(1\le X\le5\),\(1\le Y\le7\),\(1\le Z\le5\)。

思路

发现本题直接统计合法的序列很难解决去重问题,考虑容斥,即用总的方法数出不合法的方案数。

由于 \(a \in [1,10]\),总的方案数就是 \(10^n\)。注意到 \(X+Y+Z \leq 17\)。可以考虑状压。

假设当前枚举的数为 \(i\),那么加上这个数后序列是否合法,就是看是否原序列的后缀是否满足 \(x+y+z-i\),\(y+z-i\),\(z-i\) 都出现了。那么就可以设 \(f[i][j]\) 表示当前枚举到第 \(i\) 个数,当前枚举的序列后缀状态为 \(j\) 时的不合法序列方案数。

对于一个状态 \(j\),它在二进制表示下的第 \(i\) 位为 \(1\) 就表示存在一个后缀为 \(i\),当加入一个新的数 \(k\) 时,后缀 \(i\) 就更新为了 \(k\),只需要将原状态向前移动 \(k\) 位再把 \(2^k\) 加进状态即可。由于 \(X+Y+Z \leq 17\),大于 \(17\) 的后缀就没有必要考虑了,可以直接略去。而为了避免出现合法序列,自然后缀中不能同时出现 \(x+y+z\),\(y+z\) 和 \(z\),在转移的时候只需要判断一下当前状态是否包含了该合法状态即可。

code:

#include<cstdio>
#include<cstring>
#include<algorithm> 
using namespace std;
const int N=55,mod=1e9+7,M=1<<20;
int n,m,x,y,z,f[N][M],ans;
int main()
{
//	freopen("seq.in","r",stdin);
//	freopen("seq.out","w",stdout);
	scanf("%d%d%d%d",&n,&x,&y,&z);ans=1;m=(1<<x+y+z)-1;
	for(int i=1;i<=n;i++) ans=1ll*ans*10%mod;
	int state=((1<<x+y+z-1))|((1<<y+z-1))|(1<<z-1);f[0][0]=1;
	for(int i=1;i<=n;i++)
	    for(int j=0;j<=m;j++)
	        if(f[i-1][j]&&(j&state)!=state)
	            for(int k=1;k<=10;k++)
	            {
	            	f[i][((j<<k)|(1<<k-1))&m]+=f[i-1][j];
	            	f[i][((j<<k)|(1<<k-1))&m]%=mod;
				}
	for(int i=0;i<=m;i++)
	    if((i&state)!=state)
	    {
	    	ans=(ans-f[n][i]+mod)%mod;
		}
	printf("%d\n",ans);
	return 0;
}

标签:10,le,后缀,合法,ARC058C,include,序列,AT1975,dp
来源: https://www.cnblogs.com/NLCAKIOI/p/16508458.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有