SCU - 4437 Carries

在这里插入图片描述
在这里插入图片描述
大致题意:定义h(x , y)为 x + y 的进位次数 ,求给定(i , j)范围内所有h(i , j)的和

分析:一一枚举所有每组数字进位复杂度是O(n ^ 2),考虑二分找到符合题意的位置,对于每次进位,我们只处理一次,ai <= 109, 取9次模即可

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

typedef long long ll;
const int N = 1e5 + 10;

ll a[N];
ll b[N];

int main()
{
    int n , k;
    while (scanf("%d" , &n) != EOF)
    {
        memset(a , 0 , sizeof a);
        memset(b , 0 , sizeof b);
        //vector<ll> ans;
        b[0] = -1; //不用到b[0]就进行赋初值防止排序排错

        for (int i = 1; i <= n; i ++ ) cin >> a[i];

        ll j = 1; 
        ll res = 0;
        for (int k = 1; k <= 9; k ++ )
        {
            j *= 10;
            for (int i = 1; i <= n; i ++ ) b[i] = a[i] % j; // 每次取最后一位进行统计,但当比如999 % 1000 = 999 因为之前我们已经统计两次了,加上1大于等于1000,也算一次仍符合题意

            sort(b + 1 , b + n + 1);

            for (int i = 1; i <= n; i ++ )
            {
                ll l = i , r = n;
                while (l < r)
                {
                    ll mid = l + r >> 1;
                    if (b[i] + b[mid] >= j) r = mid;
                    else l = mid + 1;
                }

                if (l == i && b[l] + b[i] >= j) res += n - l;
                else if (i < l && b[i] + b[l] >= j) res += n - l + 1;

                //cout << l << " "; 

            }

            //cout << endl;
        }

        //ans.clear();
        cout << res << endl;
    }
    

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值