题解:P14644 [POI 2025/2026 #1] 表达式 / Arithmetic expression
容易发现每个数可通过加法或乘法拆分为更小的数,可以通过 dp 记录最小代价。
状态定义:设
初始化:
状态转移:对于每个
加法拆分:将
乘法拆分:将
复杂度:
代码
#include <bits/stdc++.h>
#define fo(i,begin,end) for(int i=(begin);i<=(end);++i)
using namespace std;
typedef long long ll;
const ll INF = 1e18;
ll dp[3005];
int n,a,b,c;
inline void read(int &x) {
x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void write(ll x) {
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main() {
read(n),read(a),read(b),read(c);
fo(i,1,n) dp[i]=INF;
dp[1]=a;
fo(i,2,n) {
// 加法拆分
fo(j,1,i-1) dp[i]=min(dp[i],dp[j]+dp[i-j]+b);
// 乘法拆分
int sq=sqrt(i);
fo(j,2,sq) {
if(i%j==0) {
int k=i/j;
dp[i]=min(dp[i],dp[j]+dp[k]+c);
}
}
}
fo(i,1,n) {
write(dp[i]);
if(i<n) putchar(' ');
}
putchar('\n');
return 0;
}