【题解】AT_arc153_d [ARC153D] Sum of Sum of Digits
【AT_arc153_d】题解
一:【题意】
给定一个序列a,要求找出一个非负整数x,使得f(a[1]+x)+f(a[2]+x)+...+f(a[n]+x)最小
f(x):十进制各数位和
二:【解法】
按照数位划分阶段
dp[i][j]:考虑了[1,i],第i位进位为j的数位和最小值
如何转移呢
将a按照数位[1,i-1]进行降序排序,则向i进位的一定是某个前缀
枚举x的i数位,枚举i-1阶段的进位k,统计此阶段进位tot,和a数位i之和sum
dp[i][tot]=min(dp[i][tot],dp[i-1][k]+sum)
三:【代码】
#include<bits/stdc++.h>
#define inf 2e9
using namespace std;
const int N=2e5+10;
int a[N];
int dp[11][N];
int w;
bool cmp(int a,int b){
return a%w>b%w;
}
int main(){
for(int i=0;i<11;i++){
for(int j=0;j<N;j++) dp[i][j]=inf;
}
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
w=1;
dp[0][0]=0;
for(int i=1;i<=10;i++,w*=10){
sort(a+1,a+1+n,cmp);
for(int ad=0;ad<=9;ad++){
int tot=0,sum=0;
for(int k=1;k<=n;k++){
int x=a[k]/w%10+ad;
tot+=(x>=10);
sum+=x%10;
}
dp[i][tot]=min(dp[i][tot],dp[i-1][0]+sum);
for(int k=1;k<=n;k++){
int x=a[k]/w%10+ad;
if(x==9){
tot++;
sum-=9;
}
else sum++;
dp[i][tot]=min(dp[i][tot],dp[i-1][k]+sum);
}
}
}
int ans=inf;
for(int i=0;i<=n;i++) ans=min(ans,dp[10][i]+i);
cout<<ans<<"\n";
return 0;
}

浙公网安备 33010602011771号