数位dp
程序员文章站
2022-05-12 17:55:16
...
简单的数位dp
http://codeforces.com/contest/758/problem/D
在数位dp中要特别注意0的存在,有时虽无前导0,但单有一个0是合法的
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define pow powe
using namespace std;
const int maxn=980;
typedef unsigned long long ll;
ll MAX=1e18;
char s[maxn];
ll n,dp[maxn][maxn];
ll up;
ll pow[maxn];
int main()
{
ll i,j,k,len;
cin>>n>>s;
len=strlen(s);
if(len==1&&s[0]=='0')
{
printf("0\n");
return 0;
}
for(i=0;i<len;++i)
{
s[i]-='0';
}
pow[1]=1;
up=1;
while(pow[up]<=MAX/n)
{
pow[up+1]=pow[up]*n;
up++;
if(up>80)
while(1);
}
/*
cout<<up<<endl;
for(i=0;i<=up;++i)
{
cout<<pow[i]<<endl;
}*/
memset(dp,-1,sizeof(dp));
dp[0][len]=0;
for(i=len-1;i>=0;--i)
{
if(s[i]==0)
{
for(k=up;k>=1;--k)
{
if(dp[k-1][i+1]!=-1)
{
if(dp[k-1][i+1]<=MAX)
{
if(dp[k][i]==-1)
{
dp[k][i]=dp[k-1][i+1];
}
else
{
dp[k][i]=min(dp[k][i],dp[k-1][i+1]);
}
}
}
}
continue;
}
j=i;
ll now=0;
while(j<len)
{
now*=10;
now+=s[j];
if(now>=n) break;
for(k=up;k>=1;--k)
{
if(dp[k-1][j+1]!=-1)
{
if(now<=MAX/pow[k]&&dp[k-1][j+1]<=MAX-now*pow[k])
{
if(dp[k][i]==-1)
{
dp[k][i]=dp[k-1][j+1]+now*pow[k];
}
else
{
dp[k][i]=min(dp[k][i],dp[k-1][j+1]+now*pow[k]);
}
}
}
}
j++;
}
if(i==0) break;
}
for(i=1;i<=up;++i)
{
if(dp[i][0]!=-1)
{
cout<<dp[i][0]<<endl;
break;
}
}
return 0;
}
————————
当然此题还有更简单的贪心策略,尽量取多的后缀即可
#include<bits/stdc++.h>
using namespace std;
long long base, n,ans;
char s1[79];
long long s[79];
int main()
{
int i,j;
scanf("%I64d%s",&n,s1);
base=1;
int len=strlen(s1);
for(i=0;i<len;++i) s[i]=s1[i]-48;
int pre=len-1,k=len-1;
long long t=0,b=1;
while(k>=0)
{
if(b>=1e11||t+s[k]*b>=n)
{
k++;
while(s[k]==0&&k<pre) k++;
long long sum=0;
for(i=k;i<=pre;++i)
{
sum*=10;
sum+=s[i];
}
ans+=sum*base;
base*=n;t=0;b=1;
k--;pre=k;
}
else
{
t+=s[k]*b;
b*=10;
k--;
}
}
long long sum=0;
for(i=0;i<=pre;++i)
{
sum*=10;
sum+=s[i];
}
ans+=sum*base;
printf("%I64d",ans);
return 0;
}
上一篇: wmic命令收集整理
下一篇: 关于操作符的回顾