题目链接 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1305
【题目描述】
有这样一段程序,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
【思路】
直接暴力肯定超时,这道题是对这个程序进行分析优化,有一个很重要的关键点就是有两个正整数x,y,那么f=x+y/xy的值一定是0,1,2中的一个(/表示整除),这个规律是解决这个题的关键,进一步分析可知,当x=1,y=1时,f=2.当x=2,y=2时,f=1.当x,y中有一个是1,另一个不是1的时候,f的值也是1.除此之外的所有情况都是0,根本不用计算。所以我们可以记录下整个序列中数字1和数字2的数量,计算出上述三种情况并求和即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100050;
int n;
ll a[maxn];
int main(){
while(scanf("%d",&n)==1){
int num1=0,num2=0;
for(int i=0;i<n;++i){
scanf("%lld",&a[i]);
if(1==a[i]) ++num1;
if(2==a[i]) ++num2;
}
int other=n-num1-num2;
ll ans=0;
ans+=2*(num1*(num1-1)/2);//1和1的组合是2
ans+=1*(num2*(num2-1)/2);//2和2的组合是1
ans+=num1*(num2+other);//1和不是1的所有数的组合是1
printf("%lld\n",ans);
}
return 0;
}