51nod 1305 Pairwise Sum and Divide

有这样一段程序,fun会对整数数组A进行求值,其中Floor表示向下取整:

 

fun(A)

    sum = 0

    for i = 1 to A.length

        for j = i+1 to A.length

            sum = sum + Floor((A[i]+A[j])/(A[i]*A[j])) 

    return sum

 

给出数组A,由你来计算fun(A)的结果。例如:A = {1, 4, 1},fun(A) = [5/4] + [2/1] + [5/4] = 1 + 2 + 1 = 4。

Input

第1行:1个数N,表示数组A的长度(1 <= N <= 100000)。
第2 - N + 1行:每行1个数A[i](1 <= A[i] <= 10^9)。

Output

输出fun(A)的计算结果。

Input示例

3
1 4 1

Output示例

4


思路:
这里用数学公式化简就是 1/a[i]+1/a[j] ,然后统计发现每个数字出现的次数是 n-2 次,所以就用公式算出 (n-2)*(1/a[i])  i from 1 to n;
但是这样算出来是错误的!!因为没有考虑 1/a[i]+1/a[j] 向下取整。

 

但是再分析一下:

 

对于1,(n+1)/(n*1) = 1+1/n,然后就是组合问题,从 m个1里面取出一个 1,再从所有的数里面取出一个数 (这里不用考虑再取一个1结果是2的问题,因为所有的1重复计算了一次)

至于2,只能是 1/2+1/2=1,所以从m个2里面再选出一个2,再从 m-1个2里面选出一个2

其他的数就没办法产生1,所以只要统计三种数的个数。

 

代码如下:

#include <stdio.h>

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int i,num;
        int c1=0,c2=0,c3=0;
        for(i=0; i<n; ++i)
        {
            scanf("%d",&num);
            if(num==1) ++c1;
            else if(num==2) ++c2;
            else ++c3;
        }
        long long ans=0;
        ans+=(long long)c1*(c1+c2+c3-1);
        ans+=(long long)c2*(c2-1)/2;
        printf("%I64d\n",ans);
    }

    return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值