AHOI2022山河重整 题解
首先容易得到 的解法,容易观察得出任意时刻范围都应是 否则直接寄了。
考察 使得 都能凑出但 不行。则有 ,令 表示其方案数。
可以考虑总方案减去不可行的方案,而不可行的方案可以依据更小的 求出。
考察这种最多只能加 的背包,其实就是对每个 对 做完全背包。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
#define inf 1e9
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,mod,dp[maxn],ans,pw[maxn],f[maxn];
inline void add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
inline void solve(int n){
if(n<=1)return;solve(n/2);
for(int i=0;i<=n;i++)f[i]=0;
int lim=sqrt(2*n);
for(int i=lim;i>=1;i--){
for(int j=n;j>i;j--)f[j]=f[j-i];
for(int j=i;j>=1;j--)f[j]=0;
for(int j=0;j+(j+2)*i<=n;j++)add(f[j+(j+2)*i],dp[j]);
for(int j=i;j<=n;j++)add(f[j],f[j-i]);
}for(int i=n/2+1;i<=n;i++)add(dp[i],mod-f[i]);
}
int main(){
n=read(),mod=read();
dp[0]=pw[0]=1;
for(int i=1;i<=n;i++)
pw[i]=(pw[i-1]+pw[i-1])%mod;
int lim=sqrt(2*n);
for(int i=lim;i>=1;i--){
for(int j=n;j>i;j--)dp[j]=dp[j-i];
for(int j=i;j>=1;j--)dp[j]=0;
for(int j=i;j<=n;j++)add(dp[j],dp[j-i]);
}solve(n);
for(int i=0;i<n;i++)
ans=(ans+1ll*dp[i]*pw[n-i-1])%mod;
ans=(pw[n]-ans+mod)%mod;
printf("%d\n",ans);
return 0;
}
深深地感到自己的弱小。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具