51Nod 1305 - Pairwise Sum and Divide(思维)

题目链接 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;
}
posted @ 2018-03-09 22:27  不想吃WA的咸鱼  阅读(88)  评论(0编辑  收藏  举报