P7690 [CEOI2002] A decorative fence 题解
cnblogs
如果只是询问方案数,是 P2467 [SDOI2010] 地精部落 这道题,设 \(f_{i,j,1/0}\) 表示以 \(j\) 个数中从小到大的第 \(i\) 个数处于高/低位开头的方案数。
显然有
\[\begin{aligned}
\begin{cases}
f_{i,j,1}=\sum_{k=1}^{i-1}f_{k,j-1,0}\\
f_{i,j,0}=\sum_{k=i}^{j-1}f_{k,j-1,1}
\end{cases}
\end{aligned}\]
朴素的转移是 \(O(n^3)\) 的,拿前缀和优化一下可以做到 \(O(n^2)\)。
处理出来这个后,我们利用倍增的思想查找每一位应该停留在哪个数字上,如果加上这个数字的方案数后,当前总方案数大于等于 \(C\),则这一位应该填这个数字。
具体来说,可以通过记录这一位处于高位还是低位,然后找出每一位后递归下一位来实现。具体看代码。
#include<bits/stdc++.h> #define int long long typedef long long ll; typedef unsigned long long ull; inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;} const int N=25; int n,f[N][N][N],C,ans[N]; inline void work(int x,int now,int sum,int pd){ ans[n-sum]=x; if(!sum)return; if(pd==-1||pd==1){ for(int i=1;i<x;++i){ if(now+f[i][sum][0]>=C){ work(i,now,sum-1,0); return; } now+=f[i][sum][0]; } } if(pd==-1||pd==0){ for(int i=x;i<=sum;++i){ if(now+f[i][sum][1]>=C){ work(i,now,sum-1,1); return; } now+=f[i][sum][1]; } } \\ 递归查找,pd=1表示当前处于高位找低位,pd=0反之,pd=-1表示当前是开头,找高低位无所谓。 } signed main(){ // freopen("in.in","r",stdin);freopen("out.out","w",stdout); std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); f[1][1][0]=1;f[1][1][1]=1; for(int j=2;j<=20;++j){ for(int i=1;i<=j;++i){ for(int k=1;k<i;++k){ f[i][j][1]+=f[k][j-1][0]; } for(int k=i;k<=j-1;++k){ f[i][j][0]+=f[k][j-1][1]; } } } int T=read(); while(T--){ memset(ans,0,sizeof(ans)); n=read(),C=read(); int st=0,zc=0; for(int i=1;i<=n;++i){ zc+=f[i][n][0]+f[i][n][1]; if(zc>=C){st=i;zc-=f[i][n][0]+f[i][n][1];break;} } work(st,zc,n-1,-1); std::vector<int> v; for(int i=1;i<=n;++i)v.push_back(i); v.erase(v.begin()+st-1); for(int i=2;i<=n;++i){ int zc=ans[i]; ans[i]=v[ans[i]-1]; v.erase(v.begin()+zc-1); } for(int i=1;i<=n;++i)std::cout<<ans[i]<<' ';std::cout<<'\n'; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?