P5261数字理论题解

题目链接
找数字,一眼数位dp。

考虑设计状态 f(k,s,x,p),表示当前在第 k 位,数字之和为 s,这一位给下一位进位为 x,乘 D 后和为 p

转移很显然:

f(i+1,s+Δcur,x+ΔcurD10,p+(x+ΔcurD)mod10)=f(i+1,s+Δcur,x+ΔcurD10,p+(x+ΔcurD)mod10)orf(i,s,x,p)

这个方程可以考虑用bitset优化,因为如果前三个状态相同,对于 p 是统一进行加操作的。故这里可以通过左移来实现转移。

我们从低位向高位枚举,即可得到每一种方案是否合法。

对于统计答案——

因为要求最小的,故应从高位到低位,每一位都从小到大枚举,判断是否合法。注意,由于乘 D 后可能变成 K+1 位数,故对于最高位,其 p 值不一定为 P(还可能是 Px)。

Code:

#include<bits/stdc++.h>
using namespace std;
int K, S, P, D;
int ans[105];
bitset<1023> f[102][1023][10];//P K S 进位
int main(){
scanf("%d%d%d%d", &K, &S, &P, &D);
f[0][0][0][0] = 1;
for(int i = 0; i<K; i++){
for(int j = 0;j<=i*9; j++){
for(int k = 0; k<=9; k++){
for(int cur = (i==(K-1)); cur<=9; cur++){
int sum = cur*D+k;
f[i+1][cur+j][sum/10]|=(f[i][j][k]<<(sum%10));
}
}
}
}
int x, ts, tp, tsum;
int tmps = S, tmpp = P;
bool flag = 0;
for(int i = 0; i<=9; i++){
if(P>=i&&f[K][S][i][P-i]){//注意,进位后可能为K+1位数xwx
x = i;
flag = 1;
tmpp-=i;
break;
}
}
if(!flag){
puts("-1");
}
else{
for(int i = K; i>=1; i--){
bool flag2 = 0;
for(int cur = (i==K); cur<=9; cur++){
for(int px = 0; px<=9; px++){
tsum = px+cur*D;
ts = tmps-cur;
tp = tmpp-(tsum%10);
if(ts<0 || tp < 0 || (tsum/10)!=x || !f[i-1][ts][px][tp]){
continue;
}
tmps = ts;
tmpp = tp;
x = px;
ans[i] = cur;
flag2 = 1;
if(flag2){
break;
}
}
if(flag2){
break;
}
}
}
for(int i = K; i>=1; i--){
printf("%d", ans[i]);
}
}
system("pause");
return 0;
}
posted @   霜木_Atomic  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示