有这样一段程序,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;
}