P5261数字理论题解
题目链接
找数字,一眼数位dp。
考虑设计状态
转移很显然:
这个方程可以考虑用bitset优化,因为如果前三个状态相同,对于
我们从低位向高位枚举,即可得到每一种方案是否合法。
对于统计答案——
因为要求最小的,故应从高位到低位,每一位都从小到大枚举,判断是否合法。注意,由于乘
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; }