P2926 [USACO08DEC]Patting Heads S

在这里插入图片描述

在这里插入图片描述
这道题很容易会想到O(n ^ 2)的算法,但是这个肯定会超时,比如我。最后以55分草草收场,改进以后就有100分啦.是这样的,他不是让我们分别求每头牛手上的数字可以整除多少头其他牛上手的数字吗?O(n^2)的算法就是用每头牛分别去判断其他牛的数字是否可以整除…换成另外一钟更快的算法是这样的,首先我们记录每头牛手上的数字有多少个,比如我们在输入的时候 如果输入5就 让b[5]++ 输入的是6 就让b[6]++ 输入完毕以后每头牛手上的数字每个数字的个数都会记录了下来…

 int n,num=0;
        memset(b,0, sizeof(b));
        memset(res,0,sizeof(res));
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            b[a[i]]++;
        }

这时候再去分别判断每头牛手上的数字可以整除多少头其他牛手上的数字

 for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=sqrt(a[i]);j++)
           {
               if(a[i]%j==0)
               {
                   res[i]+=b[j]+b[a[i]/j];
               }
               if(j*j==a[i])
               {
                   res[i]-=b[j];
               }
           }
           res[i]--;//减去自身
       }

解释一下上面的代码,为什么是j<=sqrt(a[i]), 你可以自己想想一个数的因子.比如12的因子 可以是 1 2 3 4 6 12 又比如 16 的因子 1 2 4 8 16 有没有发现什么

在这里插入图片描述
连着的两个相乘会等于 12 也就是我们只需要知道 1 2 3 就可以得到 4 6 12

在这里插入图片描述
连着的相乘会等于 16 也就是我们只需要得到 1 2 4 就可以得到 16 8 4

这样就可以避免遗漏了 也避免了重复 同时也节省了时间

但是也要注意 :如果开平方是一个整数 会重复算一次 所以如果j*j==a[i] 要把重复的减掉

下面是完整的 AC代码~

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define Max 1000001
int b[Max];
int a[Max];
int res[Max];
    int main()
    {
        int n,num=0;
        memset(b,0, sizeof(b));
        memset(res,0,sizeof(res));
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            b[a[i]]++;
        }
       for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=sqrt(a[i]);j++)
           {
               if(a[i]%j==0)
               {
                   res[i]+=b[j]+b[a[i]/j];
               }
               if(j*j==a[i])
               {
                   res[i]-=b[j];
               }
           }
           res[i]--;//减去自身
       }
       for(int i=1;i<=n;i++)
       {
           cout<<res[i]<<endl;
       }
        return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值