【一句话题意】有一个序列,定义f(x)为x在十进制下的位数,特别地,求对于序列
Σ
1
≤
i
<
j
≤
n
f
(
a
i
+
a
j
)
\Sigma_{1≤i<j≤n}f(a_i+a_j)
Σ1≤i<j≤nf(ai+aj)
【分析】先将序列从小到大排序。枚举i点,再二分i点左边最小的使
a
i
a_i
ai进位的点。
时间复杂度
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)
【code】
考场上脑抽写的,常数大得离谱且非常的丑,但竟然过了。
不想改。。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
#define rint register int
using namespace std;
const int maxn=1e6+1000;
int n,a[maxn];
inline void read(int &x){
x=0;char tmp=getchar();
while(tmp<'0'||tmp>'9') tmp=getchar();
while(tmp>='0'&&tmp<='9') x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
}
inline int count_num(rint x){
if(x>=10000){
if(x>=1e6){
if(x>=1e8) return 9;
else if(x>=1e7) return 8;
else return 7;
}
else{
if(x>=1e5) return 6;
else return 5;
}
}
else{
if(x>=100){
if(x>=1000) return 4;
return 3;
}
else{
if(x>=10) return 2;
else return 1;
}
}
// rint cnt=0;
// while(x>0) x/=10,cnt++;
// return cnt;
}
inline int ld(rint l,rint r,rint d,rint num){
rint ans,mid;
while(l<=r){
mid=l+r>>1;
if(count_num(a[mid]+num)<d) l=mid+1;
else r=mid-1,ans=mid;
}
return ans;
}
signed main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
cin>>n;
for(rint i=1;i<=n;i++)
read(a[i]);
sort(a+1,a+n+1);
int ans=0;
for(rint i=2;i<=n;i++){
int d1=count_num(a[i]+a[i-1]),d2=count_num(a[i]+a[1]),p=i-1;
for(rint j=d1;j>=d2;j--){
ans+=(p-ld(1,p,j,a[i])+1)*j;
p=ld(1,p,j,a[i])-1;
}
}
cout<<ans<<endl;
return 0;
}