1. 程式人生 > >SCU 4437 Carries(二分亂搞)題解

SCU 4437 Carries(二分亂搞)題解

題意:問任意兩對ai,aj相加的總進位數為多少。比如5,6,95分為(5,6)(5,95)(6,95),進位數 = 1 + 2 + 2 = 5

思路:顯然暴力是會超時的。我們可以知道總進位數等於每一位進位數之和,所以我們可以把10個位數的進位分開算,每次%10^k,排序後用二分找到剛好的位置,然後算總數。

好像是唯一一次寫二分一次A的題。

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include
<queue> #include<cmath> #include<map> #include<set> #include<vector> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; const ll seed = 131; ll a[maxn], b[maxn], k; ll fac[15]; int mid(int l, int r, ll num){ int m, ans = r + 1; while(l <= r){ m
= (l + r) >> 1; if(num + b[m] >= fac[k]) ans = m; if(num + b[m] < fac[k]) l = m + 1; else r = m - 1; } return ans; } int main(){ int n; fac[0] = 1; for(int i = 1; i <= 10; i++) fac[i] = fac[i - 1] * 10; while(~scanf("%d", &n)){ k
= 0; ll ans = 0; for(int i = 1; i <= n; i++) scanf("%lld", &a[i]); for(int i = 1; i <= 10; i++){ k = i; for(int i = 1; i <= n; i++) b[i] = a[i] % fac[k]; sort(b + 1, b + n + 1); for(int i = 1; i <= n; i++){ int pos = mid(i + 1, n, b[i]); ans += (n - pos + 1); } } printf("%lld\n", ans); } return 0; }