题目链接
题意
给一个数组{a},定义 h(a,b)为在十进制下 a + b 与 a 的位数差,求区间0到n任意两个数h(a,b)的和,0的位数为1。
思路
- 利用二分求解答案,solve(l,r)=solve(l,mid)+solve(mid+1,r)+前半个区间和后半个区间的位数差
- 对于两个区间的位数差,如果h(a,b)中a为一位数,如果想让答案加1,则b应该大于10-a,因此可对后半个区间进行排序,求分别求大于(10-a、100-a、1000-a…)的个数即可。
参考代码
#include<bits/stdc++.h>
using namespace std;
int aa[100100];
int bb[10]={10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
long long solve(int l,int r)
{
if(l==r)return 0;
long long ans=0;
int mid=(l+r)/2;
ans+=solve(l,mid)+solve(mid+1,r);
sort(aa+mid+1,aa+r+1);
for(int i=l;i<=mid;i++)
{
for(int j=0;j<9;j++)
{
if(bb[j]>aa[i])
{
ans+=aa+r+1-lower_bound(aa+mid+1,aa+r+1,bb[j]-aa[i]);
}
}
}
return ans;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>aa[i];
}
long long ans=solve(0,n-1);
cout<<ans<<endl;
}