[冲刺国赛2022] 模拟赛5
书
题目描述
对于一个长度为 的排列 ,如果 ,那么 ;否则
现在给定 数组,问有多少个排列可以生成这样的
解法
考虑把 个数划分为若干个二倍链(比如 ),然后把链的其中一段拆出来放到原序列中,就可以产生 序列中连续的一段
我们按顺序扫描 数组 ,因为相同长度的链是等价类,所以我们只需要记录所有长度对应链的数量,状态数非常少。此外我们还要记录上一个填入的数,导致分裂出了两条链 。假设现在考虑到了位置 ,转移:
- 如果 ,那么枚举填入哪个数,注意这个数不能是 的尾部 或者 的头部,要不然会产生 ;然后把这个数的链分裂开来,更改链长分布的同时记录新的
- 如果 ,因为要和上一个位置形成二倍关系,所以只能用 ,那么讨论一下用哪一个即可。
还是需要把状态哈希之后存进 中,要用的时候再重新解密,时间充裕,怎么写都可以。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
using namespace std;
const int M = 45;
const int MOD = 1e9+7;
#define ll long long
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,a[M];map<ll,int> dp;
struct node
{
int b[7],x,y;
node() {x=y=0;memset(b,0,sizeof b);}
}z;
void add(int &x,int y) {x=(x+y)%MOD;}
ll encode(node s)
{
ll r=0;
for(int i=6;i>=1;i--) r=r*41+s.b[i];
r=r*7+s.x;r=r*7+s.y;
return r;
}
node decode(ll r)
{
node s;
s.y=r%7;r/=7;
s.x=r%7;r/=7;
for(int i=1;i<=6;i++) s.b[i]=r%41,r/=41;
return s;
}
signed main()
{
freopen("book.in","r",stdin);
freopen("book.out","w",stdout);
n=read();
for(int i=1;i<n;i++)
scanf("%1d",&a[i]);
for(int i=1;i<=n;i++) if(i&1)
{
int l=0;
for(int j=i;j<=n;j<<=1) l++;
z.b[l]++;
}
for(int i=1;i<=n;i++) if(i&1)
{
int l=0;
for(int j=i;j<=n;j<<=1) l++;
for(int j=1;j<=l;j++)
{
int x=j-1,y=l-j;node t=z;
t.b[l]--;t.b[x]++;t.b[y]++;
t.x=x;t.y=y;
dp[encode(t)]++;
}
}
while(!dp.empty())
{
ll h=dp.rbegin()->first;
int c=dp.rbegin()->second;
dp.erase(--dp.end());
if(!h) {printf("%d\n",c);return 0;}
node s=decode(h);int l=n,r=0;
for(int i=1;i<=6;i++) l-=s.b[i]*i;
if(a[l]==0)
{
for(int i=1;i<=6;i++) if(s.b[i])
for(int j=1;j<=i;j++)
{
int w=s.b[i]-(s.x==i)-(s.y==i);
node t=s;t.b[i]--;
t.b[t.x=j-1]++;t.b[t.y=i-j]++;
add(dp[encode(t)],1ll*c*(w+
(s.x==i&&j<i)+(s.y==i&&j>1))%MOD);
}
}
else
{
r=l;while(a[r]==a[l]) r++;l=r-l;
if(s.x>=l)
{
node t=s;t.b[t.x]--;
t.x-=l;t.y=0;t.b[t.x]++;
add(dp[encode(t)],c);
}
if(s.y>=l)
{
node t=s;t.b[t.y]--;
t.y-=l;t.x=0;t.b[t.y]++;
add(dp[encode(t)],c);
}
}
}
puts("0");return 0;
}
分类:
dp-----状压dp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2021-06-04 CF1276F Asterisk Substrings