看了论文,又看了别人博客,还是卡了我两天,看来我对字符串的感知能力真是渣....贴个博客造(bao)福(fu)社会。总结一下
把问题先分析清楚,然后充分预处理,会使后面的过程很简单。
字典序在位数相等的情况下可以转换成大小序。
注意别忽视空串,也就是null。
注意首位能否为0。
另外有个有意思的地方.. vector容器太厉害了...比如直接比较v1<v2是比较v1和v2的字典序。又比如partial_sum、accumulate
函数。
代码(http://blog.watashi.ws/1213/andrew-stankevich-6-solution/ZOJ2599/ 这个NB.. 我贴的代码是为了以后自己复习的...参考了链接里的代码..)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
long long se[20][200];
long long sl[20][200];
long long le[200][20];
long long ll[200][20];
void Init()
{
long long i,j,k;
memset(se,0,sizeof(se));
memset(sl,0,sizeof(sl));
se[0][0]=1,le[0][0]=1;
for(i=1;i<20;++i)
for(j=0;j<200;++j)
{
for(k=0;k<10;++k)
if(j-k>=0)
se[i][j]+=se[i-1][j-k];
le[j][i]=se[i][j];
}
for(i=0;i<20;++i)
{
sl[i][0]=0;
for(j=1;j<200;++j)
sl[i][j]=sl[i][j-1]+se[i][j-1];
}
for(i=0;i<200;++i)
{
ll[i][0]=0;
for(j=1;j<20;++j)
ll[i][j]=ll[i][j-1]+le[i][j-1];
}
}
long long SumLess(vector<int>& n,long long sum)
{
long long i,j,tmp=0,ans=0;
for(i=0;i<n.size();++i)
tmp+=n[i];
if(tmp<sum)
ans++;
for(i=0;i<n.size();++i)
{
for(j=0;j<n[i];++j)
if(sum-j>=0)
ans+=sl[n.size()-i-1][sum-j];
sum-=n[i];
if(sum<0)
break;
}
return ans-1;
}
long long LexLess(vector<int>& n,long long sum,vector<int>& k)
{
long long i,j,ans=0,tmp=sum,sum2=0;
for(i=0;i<k.size();++i)
{
if(sum==0)
ans++;
for(j=(i==0?1:0);j<k[i];++j)
if(sum>=j)
{
ans+=ll[sum-j][n.size()-i-1];
}
sum-=k[i];
if(sum<0)
break;
}
sum=tmp;
if(k<=n)
{
for(i=0;i<k.size();++i)
{
for(j=(i==0?1:0);j<k[i];++j)
if(sum>=j)
ans+=le[sum-j][n.size()-i-1];
sum-=k[i];
if(sum<0)
break;
}
}
else
{
for(i=0;i<n.size();++i)
{
for(j=(i==0?1:0);j<n[i];++j)
if(sum>=j)
ans+=le[sum-j][n.size()-i-1];
sum-=n[i];
if(sum<0)
break;
}
if(sum==0)
ans++;
}
return ans;
}
long long Work1(vector<int>& n,vector<int>& k)
{
long long i,sum=0;
for(i=0;i<k.size();++i)
sum+=k[i];
return SumLess(n,sum)+LexLess(n,sum,k)+1;
}
long long Work2(vector<int>& n,long long k)
{
long long l=1,r=200,mid,ret,sum,i,j;
while(l!=r)
{
mid=((l+r)>>1)+1;
if(SumLess(n,mid)<k)
l=mid;
else
r=mid-1;
}
sum=l;
k-=SumLess(n,sum);
k--;
vector<int> ans;
ans.clear();
while(ans.size()<n.size())
{
ans.push_back(9);
while(ans.back()>=0&&LexLess(n,sum,ans)>k)
{
ans.back()--;
}
if(ans.back()<0)
break;
}
if(ans.back()<0)
ans.pop_back();
ret=0;
for(i=0;i<ans.size();++i)
ret=ret*10+ans[i];
return ret;
}
vector<int> ToVector(long long n)
{
vector<int> v;
while(n)
{
v.push_back(n%10);
n/=10;
}
reverse(v.begin(),v.end());
return v;
}
int main()
{
vector<int> nv,kv;
long long n,k;
Init();
while(cin>>n>>k)
{
if(n==0&&k==0)
break;
nv=ToVector(n);
kv=ToVector(k);
cout<<Work1(nv,kv)<<" ";
cout<<Work2(nv,k)<<endl;
}
return 0;
}