Problem:
たくさんの数字 (Many Digits)
問題文
JOI 高校の葵さんは，
N
行
N
列のマス目の各マスに整数を十進数表記で書くことにした．具体的には上から
i
行目 (
1 ≦ i ≦ N
)，左から
j
列目 (
1 ≦ j ≦ N
) のマスには
A
i
+ B
j
を十進数表記で書く．
葵さんは数字を何文字書くことになるかを知りたい．つまり，葵さんが書く
N
2
個の整数の桁数の合計を求めたい．
A
i
(
1 ≦ i ≦ N
) と
B
j
(
1 ≦ j ≦ N
) が与えられたとき，葵さんが書く
N
2
個の整数の桁数の合計を求めるプログラムを作成せよ．
制約
1 ≦ N ≦ 150 000
．
1 ≦ A
i
≦ 999 999 999
(
1 ≦ i ≦ N
)．
1 ≦ B
j
≦ 999 999 999
(
1 ≦ j ≦ N
)．
入力される値はすべて整数である．
入力
入力は以下の形式で与えられる．
N
A
1
A
2
…
A
N
B
1
B
2
…
B
N
出力
葵さんが書く
N
2
個の整数の桁数の合計を
1
行で出力せよ．
入出力例
入力例 1
3
97 79 7
20 2 21
出力例 1
20
葵さんが各マスに書く整数は以下の図のようになる．
例えば，葵さんは上から
1
行目，左から
1
列目のマスには
A
1
+ B
1
= 97 + 20 = 117
を書く．また，上から
3
行目，左から
2
列目のマスには
A
3
+ B
2
= 7 + 2 = 9
を書く．
葵さんが書く
9
個の整数は
117, 99, 118, 99, 81, 100, 27, 9, 28
であり，それぞれの桁数は
3, 2, 3, 2, 2, 3, 2, 1, 2
である．
よって，葵さんが書く
9
個の整数の桁数の合計は
3 + 2 + 3 + 2 + 2 + 3 + 2 + 1 + 2 = 20
となるため，
20
を出力する．
入力例 2
4
8 97 996 9995
1 2 3 4
出力例 2
46
葵さんが各マスに書く数字は以下の図のようになる．
例えば，葵さんは上から
2
行目，左から
3
列目のマスには
A
2
+ B
3
= 97 + 3 = 100
を書く．この整数の桁数は
3
である．また，上から
4
行目，左から
2
列目のマスには
A
4
+ B
2
= 9 995 + 2 = 9 997
を書く．この整数の桁数は
4
である．
葵さんが書く
16
個の整数の桁数の合計は
46
となるため，
46
を出力する．
入力例 3
1
500000000
500000000
出力例 3
10
葵さんが書く整数は
1
個で，その値は
500 000 000 + 500 000 000 = 1 000 000 000
である．この整数の桁数は
10
である．
よって，葵さんが書く
1
個の整数の桁数の合計は
10
となるため，
10
を出力する．
入力例 4
7
436981378 523812834 456708479 413571178 506402783 598271009 523936624
401203104 501634329 506090236 527167431 485527116 439442403 568364549
出力例 4
463
情報オリンピック日本委員会
作『日本情報オリンピック第4回女性部門 本選 競技課題』

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;
    vector<ll> A(N), B(N);
    for (int i = 0; i < N; i++) cin >> A[i];
    for (int i = 0; i < N; i++) cin >> B[i];

    sort(B.begin(), B.end());

    // 桁数境界
    vector<ll> L, R;
    for (ll p = 1; p <= (ll)1e18; p *= 10) {
        L.push_back(p);
        R.push_back(p * 10 - 1);
    }

    ll ans = 0;
    for (int i = 0; i < N; i++) {
        for (int d = 1; d <= 18; d++) {
            ll low = L[d - 1] - A[i];
            ll high = R[d - 1] - A[i];
            auto it1 = lower_bound(B.begin(), B.end(), low);
            auto it2 = upper_bound(B.begin(), B.end(), high);
            ans += (it2 - it1) * 1LL * d;
        }
    }

    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5760
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 998244353
#define MOD 1000000007
#define EPS 0.000000001




#define SIZE 150005

int N;
ll A[SIZE],B[SIZE],POW[12];

int calc(ll num){

	int ret = 0;
	do{
		ret++;
		num /= 10;

	}while(num > 0);
	return ret;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 12; i++){

		POW[i] = POW[i-1]*10;
	}

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
	}
	for(int i = 0; i < N; i++){
		scanf("%lld",&B[i]);
	}
	sort(B,B+N);

	ll ans = 0;
	for(int i = 0; i < N; i++){
		int base_d = calc(A[i]);

		for(ll d = base_d; d <= 11; d++){
			ll mini = POW[d-1]-A[i];
			ll maxi = (POW[d]-1)-A[i];

			int left = 0,right = N-1,mid = (left+right)/2;
			ll L = N;

			//mini以上となる最も左のインデックス
			while(left <= right){
				if(B[mid] >= mini){

					L = mid;
					right = mid-1;

				}else{

					left = mid+1;
				}
				mid = (left+right)/2;
			}

			//maxi以下となる最も右にのインデックス
			left = 0,right = N-1,mid = (left+right)/2;
			ll R = -1;

			while(left <= right){
				if(B[mid] <= maxi){

					R = mid;
					left = mid+1;
				}else{

					right = mid-1;
				}
				mid = (left+right)/2;
			}

			ans += d*max(0LL,R-L+1);
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 5916
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 998244353
#define MOD 1000000007
#define EPS 0.000000001




#define SIZE 150005

int N;
ll A[SIZE],B[SIZE],POW[12];

int calc(ll num){

	int ret = 0;
	do{
		ret++;
		num /= 10;

	}while(num > 0);
	return ret;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 12; i++){

		POW[i] = POW[i-1]*10;
	}

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
	}
	for(int i = 0; i < N; i++){
		scanf("%lld",&B[i]);
	}
	sort(B,B+N);

	ll ans = 0;
	for(int i = 0; i < N; i++){
		int base_d = calc(A[i]);
		//printf("\nA[%d]:%lld base_d:%d\n",i,A[i],base_d);

		for(ll d = base_d; d <= 11; d++){
			ll mini = POW[d-1]-A[i];
			ll maxi = (POW[d]-1)-A[i];

			//printf("mini:%lld maxi:%lld\n",mini,maxi);

			int left = 0,right = N-1,mid = (left+right)/2;
			ll L = N;

			//mini以上となる最も左のインデックス
			while(left <= right){
				if(B[mid] >= mini){

					L = mid;
					right = mid-1;

				}else{

					left = mid+1;
				}
				mid = (left+right)/2;
			}

			//maxi以下となる最も右にのインデックス
			left = 0,right = N-1,mid = (left+right)/2;
			ll R = -1;

			while(left <= right){
				if(B[mid] <= maxi){

					R = mid;
					left = mid+1;
				}else{

					right = mid-1;
				}
				mid = (left+right)/2;
			}
			//printf("R:%d L:%d\n",R,L);
			ans += d*max(0LL,R-L+1);
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 5956
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 998244353
#define MOD 1000000007
#define EPS 0.000000001




#define SIZE 150005

int N;
ll A[SIZE],B[SIZE],POW[12];

int calc(ll num){

	int ret = 0;
	do{
		ret++;
		num /= 10;

	}while(num > 0);
	return ret;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 12; i++){

		POW[i] = POW[i-1]*10;
	}

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
	}
	for(int i = 0; i < N; i++){
		scanf("%lld",&B[i]);
	}
	sort(B,B+N);

	ll ans = 0;
	for(int i = 0; i < N; i++){
		int base_d = calc(A[i]);
		//printf("\nA[%d]:%lld base_d:%d\n",i,A[i],base_d);

		for(ll d = base_d; d <= 11; d++){
			ll mini = POW[d-1]-A[i];
			ll maxi = (POW[d]-1)-A[i];

			//printf("mini:%lld maxi:%lld\n",mini,maxi);

			int left = 0,right = N-1,mid = (left+right)/2;
			ll L = N;

			//mini以上となる最も左のインデックス
			while(left <= right){
				if(B[mid] >= mini){

					L = mid;
					right = mid-1;

				}else{

					left = mid+1;
				}
				mid = (left+right)/2;
			}

			//maxi以下となる最も右にのインデックス
			left = 0,right = N-1,mid = (left+right)/2;
			ll R = -1;

			while(left <= right){
				if(B[mid] <= maxi){

					R = mid;
					left = mid+1;
				}else{

					right = mid-1;
				}
				mid = (left+right)/2;
			}
			//printf("R:%d L:%d\n",R,L);
			ans += d*max(0LL,R-L+1);
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.3821138211382114
time_ms: 60
memory_kb: 5888
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 998244353
#define MOD 1000000007
#define EPS 0.000000001




#define SIZE 150005

int N;
ll A[SIZE],B[SIZE],POW[12];

int calc(ll num){

	int ret = 0;
	do{
		ret++;
		num /= 10;

	}while(num > 0);
	return ret;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 12; i++){

		POW[i] = POW[i-1]*10;
	}

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
	}
	for(int i = 0; i < N; i++){
		scanf("%lld",&B[i]);
	}
	sort(B,B+N);

	ll ans = 0;
	for(int i = 0; i < N; i++){
		int base_d = calc(A[i]);
		//printf("\nA[%d]:%lld base_d:%d\n",i,A[i],base_d);

		for(int d = base_d; d <= 10; d++){
			ll mini = POW[d-1]-A[i];
			ll maxi = (POW[d]-1)-A[i];

			//printf("mini:%lld maxi:%lld\n",mini,maxi);

			int left = 0,right = N-1,mid = (left+right)/2;
			int L = N;

			//mini以上となる最も左のインデックス
			while(left <= right){
				if(B[mid] >= mini){

					L = mid;
					right = mid-1;

				}else{

					left = mid+1;
				}
				mid = (left+right)/2;
			}

			//maxi以下となる最も右にのインデックス
			left = 0,right = N-1,mid = (left+right)/2;
			int R = -1;

			while(left <= right){
				if(B[mid] <= maxi){

					R = mid;
					left = mid+1;
				}else{

					right = mid-1;
				}
				mid = (left+right)/2;
			}
			//printf("R:%d L:%d\n",R,L);
			ans += d*max(0,R-L+1);
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.3821138211382114
time_ms: 50
memory_kb: 5796
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
//#define MOD 998244353
#define MOD 1000000007
#define EPS 0.000000001




#define SIZE 150005

int N;
ll A[SIZE],B[SIZE],POW[12];

int calc(ll num){

	int ret = 0;
	do{
		ret++;
		num /= 10;

	}while(num > 0);
	return ret;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 12; i++){

		POW[i] = POW[i-1]*10;
	}

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
	}
	for(int i = 0; i < N; i++){
		scanf("%lld",&B[i]);
	}
	sort(B,B+N);

	int ans = 0;
	for(int i = 0; i < N; i++){
		int base_d = calc(A[i]);
		//printf("\nA[%d]:%lld base_d:%d\n",i,A[i],base_d);

		for(int d = base_d; d <= 10; d++){
			ll mini = POW[d-1]-A[i];
			ll maxi = (POW[d]-1)-A[i];

			//printf("mini:%lld maxi:%lld\n",mini,maxi);

			int left = 0,right = N-1,mid = (left+right)/2;
			int L = N;

			//mini以上となる最も左のインデックス
			while(left <= right){
				if(B[mid] >= mini){

					L = mid;
					right = mid-1;

				}else{

					left = mid+1;
				}
				mid = (left+right)/2;
			}

			//maxi以下となる最も右にのインデックス
			left = 0,right = N-1,mid = (left+right)/2;
			int R = -1;

			while(left <= right){
				if(B[mid] <= maxi){

					R = mid;
					left = mid+1;
				}else{

					right = mid-1;
				}
				mid = (left+right)/2;
			}
			//printf("R:%d L:%d\n",R,L);
			ans += d*max(0,R-L+1);
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.3821138211382114
time_ms: 50
memory_kb: 5672
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <chrono>
#pragma GCC target ("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i,n) for (ll i = 0;i < (ll)(n);i++)
#define Yes cout << "Yes" << "\n"// YESの短縮
#define No cout << "No" << "\n"// NOの短縮
#define rtr0 return(0)//return(0)の短縮
#define gyakugen(x) modpow(x,mod - 2,mod);
#define agyakugen(x) modpow(x,amod - 2,amod);
using namespace std;
//using namespace ranges;
using ll = long long;//63bit型整数型
using ld = long double;//doubleよりも長い値を保存できるもの
using ull = unsigned long long;//符号がない64bit型整数
ll mod = 998244353;
ll amod = 1000000007;
ll MINF = -5000000000000000000;
ll INF = 5000000000000000000;
ll inf = 5000000000;
ll minf = -5000000000;
ll BAD = -1;
vector<ll>tate = {0,-1,0,1};//グリッド上の全探索時の四方向の上下のチェック
vector<ll>yoko = {1,0,-1,0};//グリッド上の全探索時の四方向の右左のチェック
vector<ll>eightx = {0,-1,-1,-1,0,1,1,1};//グリッド上の全探索時の八方向の上下のチェック
vector<ll>eighty = {1,1,0,-1,-1,-1,0,1};//グリッド上の全探索時の八方向の右左のチェック
vector<ll>hexsax = {0,1,1,0,-1,-1};
vector<ll>hexsay = {1,1,0,-1,-1,0};
//返り値は素数のリスト。
vector < bool > isprime;
vector < ll > Era(int n){//書き方 vector<ll>[] = Era(x); とやるとxまでの素数が出てくる。
	isprime.resize(n, true);
	vector < ll > res;
	isprime[0] = false;
	isprime[1] = false;
	for(ll i = 2; i < n; ++i) isprime[i] = true;
	for(ll i = 2; i < n; ++i) {
		if(isprime[i]) {
			res.push_back(i);
			for(ll j = i * 2; j < n; j += i) isprime[j] = false;
		}
	}
	return res;
}
//　　　　　　素数判定 21~35

long long modpow(long long a, long long n, long long mod) {
	long long res = 1;
	while (n > 0) {
		if (n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

long long npow(long long a, long long n){
    long long res = 1;
    while (n > 0) {
		if (n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}
//     モッドを使った累乗


template<class T>
struct dijkstra{
  public:
	vector<vector<pair<T,T>>>graph;
	vector<T>ans;
	priority_queue<pair<T,T>,vector<pair<T,T>>,greater<pair<T,T>>>pq;
	void do_dijkstra(T start){//頂点xからダイクストラを行う
		pq.push({0,start});
		ans[start] = 0;
		while(true){
			if(pq.empty())break;
			T cost = pq.top().first;
			T vertex = pq.top().second;
			pq.pop();
			for(T i = 0;i<graph[vertex].size();i++){
				T nextvertex = graph[vertex][i].first;
				T nextcost = graph[vertex][i].second + cost;
				if(ans[nextvertex] > nextcost){
					ans[nextvertex] = nextcost;
					pq.push({nextcost,nextvertex});
				}
			}
		}
	}
	void make_indirectedgraph(T u,T v,T cost){//無向辺のグラフ作成
		graph[u].push_back({v,cost});
		graph[v].push_back({u,cost});
	}
	void make_directedgraph(T u,T v,T cost){//有向辺のグラフ作成
		graph[u].push_back({v,cost});
	}
	T output(T end){//答えを出す
		return ans[end];
	} 
	void reset(T N){//リセット
		graph.clear();
		ans.clear();
		for(ll i = 0;i<N;i++){
			graph.push_back({vector<pair<T,T>>(0)});
			ans.push_back(INF);
		}
	}
};
template<class T>
struct unionfind {
public:
    vector<T> parent, rank;
    void reset(T N) { // 初期化
        parent.resize(N);
        rank.assign(N, 1); // 各集合のサイズを 1 にする
        for (T i = 0; i < N; i++) parent[i] = i;
    }
    T leader(T x) { // 経路圧縮による親の取得
        if (parent[x] == x) return x;
        return parent[x] = leader(parent[x]); // 経路圧縮
    }
    void marge(T x, T y) { // ランクによるマージ
        T a = leader(x), b = leader(y);
        if(a!=b){
            if (rank[a] < rank[b]) swap(a, b);
            parent[b] = a;
            rank[a] += rank[b]; // サイズを更新    
        }
    }
    bool same(T x, T y) { // 同じ集合か判定
        return leader(x) == leader(y);
    }
    T size(T x) { // 集合のサイズを取得
        return rank[leader(x)];
    }
    void check(T N) { // デバッグ用: 親の確認
        for (T i = 0; i < N; i++) cout << parent[i] << " ";
        cout << "\n";
    }
};
//セグ木
template <class S, S (*op)(S, S), S (*e)()> struct segtree {
    public:
        segtree() : segtree(0) {}
        segtree(int n) : segtree(std::vector<S>(n, e())) {}
        segtree(const std::vector<S>& v) : _n(int(v.size())){
            log = ceil_pow2(_n);
            size = 1 << log;
            d = std::vector<S>(2 * size, e());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }
  
        void set(int p, S x) {
            assert(0 <= p && p < _n);
            p += size;
            d[p] = x;
            for (int i = 1; i <= log; i++) update(p >> i);
        }
  
        S get(int p) {
            assert(0 <= p && p < _n);
            return d[p + size];
        }
  
        S prod(int l, int r) {
            assert(0 <= l && l <= r && r <= _n);
            S sml = e(), smr = e();
            l += size;
            r += size;
  
            while (l < r) {
                if (l & 1) sml = op(sml, d[l++]);
                if (r & 1) smr = op(d[--r], smr);
                l >>= 1;
                r >>= 1;
            }
            return op(sml, smr);
        }
  
        S all_prod() { return d[1]; }
  
        template <bool (*f)(S)> int max_right(int l) {
            return max_right(l, [](S x) { return f(x); });
        }
        template <class F> int max_right(int l, F f) {
            assert(0 <= l && l <= _n);
            assert(f(e()));
            if (l == _n) return _n;
            l += size;
            S sm = e();
            do{
                while (l % 2 == 0) l >>= 1;
                if (!f(op(sm, d[l]))) {
                    while (l < size) {
                        l = (2 * l);
                        if (f(op(sm, d[l]))) {
                            sm = op(sm, d[l]);
                            l++;
                        }
                    }
                    return l - size;
                }
                sm = op(sm, d[l]);
                l++;
            }while ((l & -l) != l);
            return _n;
        }
  
        template <bool (*f)(S)> int min_left(int r) {
            return min_left(r, [](S x) { return f(x); });
        }
        template <class F> int min_left(int r, F f) {
            assert(0 <= r && r <= _n);
            assert(f(e()));
            if (r == 0) return 0;
            r += size;
            S sm = e();
            do{
                r--;
                while (r > 1 && (r % 2)) r >>= 1;
                if (!f(op(d[r], sm))) {
                    while (r < size) {
                        r = (2 * r + 1);
                        if (f(op(d[r], sm))) {
                            sm = op(d[r], sm);
                            r--;
                        }
                    }
                    return r + 1 - size;
                }
                sm = op(d[r], sm);
            }while ((r & -r) != r);
            return 0;
        }
  
    private:
        int _n, size, log;
        std::vector<S> d;
  
        void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
};

//遅延セグ木
template <class S,S (*op)(S, S),S (*e)(),class F,S (*mapping)(F, S),F (*composition)(F, F),F (*id)()>
struct lazy_segtree {

    public:
        lazy_segtree() : lazy_segtree(0) {}
        lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
        lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
            log = ceil_pow2(_n);
            size = 1 << log;
            d = std::vector<S>(2 * size, e());
            lz = std::vector<F>(size, id());
            for (int i = 0; i < _n; i++) d[size + i] = v[i];
            for (int i = size - 1; i >= 1; i--) {
                update(i);
            }
        }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

    private:
        int _n, size, log;
        std::vector<S> d;
        std::vector<F> lz;
        int ceil_pow2(int n) {
            int x = 0;
            while ((1U << x) < (unsigned int)(n)) x++;
            return x;
        }
        void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
        void all_apply(int k, F f) {
            d[k] = mapping(f, d[k]);
            if (k < size) lz[k] = composition(f, lz[k]);
        }
        void push(int k) {
            all_apply(2 * k, lz[k]);
            all_apply(2 * k + 1, lz[k]);
            lz[k] = id();
        }
};

//遅延セグ木のベース
using lazyS = ll;
using lazyF = ll;//型
lazyS e(){ return 0;}//範囲外などを起こしてしまったときの返り値
lazyS op(lazyS a, lazyS b){ return a+b; }//操作したいこと
lazyS mapping(lazyF f, lazyS x){ return x+f; }//下まで伝播させたいこと
lazyF composition(lazyF f, lazyF g){ return g+f; }//まとめてやった場合おこしたいこと
lazyF id(){ return 0; }//遅延セグ木のベース
int main(){
//B以上は基本詳細を書いておくと便利　A ＝ ooの値とか　見直す時に便利
// この問題の本質
ll N;
cin >> N;
vector<ll>A(N);
vector<ll>B(N);
for(ll i = 0;i<N;i++)cin >> A[i];
for(ll i = 0;i<N;i++)cin >> B[i];
sort(A.begin(),A.end());
sort(B.begin(),B.end());
vector<ll>imos(11);
A.push_back(INF);
B.push_back(INF);
for(ll i = 0;i<N;i++){
    for(ll ii = 0;ii<=10;ii++){
        ll x = npow(10,ii);
        ll a = B[i];
        a = x-a;
        ll k = lower_bound(A.begin(),A.end(),a)-A.begin();
        if(k<N){
            imos[ii]+=(N-k);
        }
    }
}
for(ll i = 1;i<=10;i++){
    imos[i] += imos[i-1];
}
cout << imos[10] << "\n";
}
accuracy: 1
time_ms: 100
memory_kb: 7800
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)

long long count(vector<long long >& a,long long b,long long c){
    return lower_bound(a.begin(),a.end(),c)-lower_bound(a.begin(),a.end(),b);
}

int main(){
    int n;
    cin >> n;
    vector<long long> a(n),b(n);
    rep(i,n){
        cin >> a[i];
    }
    rep(i,n){
        cin >> b[i];
    }
    sort(b.begin(),b.end());
    
    long long res=0;
    rep(i,n){
        long long power10=1;
        rep(j,10){
            res += (j+1)*count(b,power10-a[i],power10*10-a[i]);
            power10*=10;
        }
    }
    cout << res << endl;
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 5492
final_rank: 8

code_snippet: #include <iostream>
#include <cstdint>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	
	uint32_t N, i, j;
	cin >> N;
	vector<int32_t> A(N), B(N);
	for (i = 0; i != N; ++i) cin >> A[i];
	for (j = 0; j != N; ++j) cin >> B[j];

	sort(B.begin(), B.end());
	uint64_t ans = 0;
	int32_t digit;
	for (i = 0; i != N; ++i)
	{
		for (digit = 1; digit != 1'000'000'000; digit *= 10)
			ans += B.end() - lower_bound(B.begin(), B.end(), digit - A[i]);
		ans += B.end() - lower_bound(B.begin(), B.end(), digit - A[i]);
	}

	cout << ans << '\n';
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4480
final_rank: 1

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<ll> a(n), b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> b[i];
    }
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    ll res = 0;
    ll base = 1;
    for (int _ = 0; _ < 11; _++) {
        int r = n;
        for (int i = 0; i < n; i++) {
            while (r and a[i] + b[r - 1] >= base) {
                r -= 1;
            }
            res += n - r;
        }
        base *= 10;
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 5468
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

int main(){
    int N;
    cin>>N;
    vector<ll> A(N),B(N);
    for(auto &a:A)cin>>a;
    for(auto &b:B)cin>>b;
    sort(B.begin(),B.end());
    ll an=0;
    for(ll i=1;i<=1e12;i*=10){
        for(auto a:A)an+=B.end()-lower_bound(B.begin(),B.end(),i-a);
    }
    cout<<an<<endl;
}
accuracy: 1
time_ms: 100
memory_kb: 5468
final_rank: 7

code_snippet: // AOJ #788
// Many Digits 2025.1.11

#include <bits/stdc++.h>
using namespace std;

// A, B はそれぞれ昇順ソート済みとする
// (A[i] + B[j]) <= X となる (i, j) の個数を二ポインタで数える
long long count_pairs_leq_X(const vector<long long> &A,
                            const vector<long long> &B,
                            long long X) {
    long long count = 0;
    int N = (int)A.size();
    int j = N - 1;
    for (int i = 0; i < N; i++) {
        while (j >= 0 && A[i] + B[j] > X) {
            j--;
        }
        // j が -1 のときは加算される個数 0
        count += (j + 1);
    }
    return count;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    int N;
    cin >> N;

    vector<long long> A(N), B(N);
    for(int i=0; i<N; i++){
        cin >> A[i];
    }
    for(int j=0; j<N; j++){
        cin >> B[j];
    }

    // ソート
    sort(A.begin(), A.end());
    sort(B.begin(), B.end());

    // 桁数が変わる境界をまとめる
    // 先頭に 0 を入れ、最後を 1,999,999,998 とする
    // (1 <= A_i, B_j <= 999999999 なので和は最大でも 1999999998)
    vector<long long> D = {
        0LL,                // <=0 の個数 (常に 0 になる)
        9LL,
        99LL,
        999LL,
        9999LL,
        99999LL,
        999999LL,
        9999999LL,
        99999999LL,
        999999999LL,
        1999999998LL       // 最大想定和
    };

    // F[i] = f(D[i]) = #( (i,j) | A_i + B_j <= D[i] )
    // 境界ごとに二ポインタで数えて格納
    vector<long long> F(D.size());
    for(int i=0; i<(int)D.size(); i++){
        F[i] = count_pairs_leq_X(A, B, D[i]);
    }

    // 桁数の合計を求める
    // D[i-1]+1 〜 D[i] が桁数 i の範囲
    // → ペア数は F[i] - F[i-1], その桁数は i
    long long ans = 0;
    // i=1(1桁) 〜 10(10桁) まで
    for(int k=1; k<=(int)D.size()-1; k++){
        long long cntRange = F[k] - F[k-1]; // その区間に入るペア数
        long long digit = k;               // k桁
        ans += digit * cntRange;
    }

    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 5468
final_rank: 2