SCU-4437 Carries(思维题)

本文介绍了一种算法,用于解决给定多个整数时,计算所有两两相加过程中产生的进位次数总和的问题。该算法通过将整数按不同位数进行分组,并在每组内进行排序及计算,最终得出所有可能配对相加时的进位总数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Carries

frog has n n integers a 1 ,a 2 ,,a n  a1,a2,…,an, and she wants to add them pairwise.

Unfortunately, frog is somehow afraid of carries (进位). She defines hardnessh(x,y) h(x,y) for adding x x and y y the number of carries involved in the calculation. For example, h(1,9)=1,h(1,99)=2 h(1,9)=1,h(1,99)=2.

Find the total hardness adding n n integers pairwise. In another word, find

 1i<jn h(a i ,a j ) ∑1≤i<j≤nh(ai,aj)
.

Input

The input consists of multiple tests. For each test:

The first line contains 1 1 integer n n (2n10 5  2≤n≤105). The second line contains n n integers a 1 ,a 2 ,,a n  a1,a2,…,an. (0a i 10 9  0≤ai≤109).

Output

For each test, write 1 1 integer which denotes the total hardness.

Sample Input

    2
    5 5
    10
    0 1 2 3 4 5 6 7 8 9

Sample Output

    1
    20

题意:给出n个数,定义h(x,y)是x+y的进位次数,例如h(1,99)=2,因为1+99进了2位,要求求出所有的数相互组合相加进位次数的总和
题解:把每个数字对10,100,...1e9取模,分别把相应取模后的数字存到集合中,在每个集合中,先排序,再枚举第1~n个数,对于每个
数,找到与它相加大于模的那些数,统计这些数的个数全部加起来就是答案

#include<cstdio>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<functional>
#include<iostream>
#include<math.h>
#include<vector>
#include<stdlib.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 5;
LL a[maxn],mod[15];
int main(){
    int n;
    mod[0]=1;
  //  freopen("in.txt","r",stdin);
    for(int i=1;i<10;i++) mod[i]=mod[i-1]*10;
    while(~scanf("%d",&n)){
        vector<int>v[10];
        for(int i=0;i<n;i++) {
            scanf("%lld",&a[i]);
            for(int j=1;j<10;j++)  //对10^j取模
                if(a[i]%mod[j]>0) v[j].push_back(a[i]%mod[j]);//存入相应的集合
        }
        LL ans=0;
        for(int i=1;i<10;i++) {
            sort(v[i].begin(),v[i].end());//从小打到排序,方便二分查找
            for(int j=0;j+1<v[i].size();j++){  //二分查找x+v[i][j]>mod[i]的x的个数
                ans+=v[i].size()-(lower_bound(v[i].begin()+j+1,v[i].end(),mod[i]-v[i][j])-v[i].begin());
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值