这道题很容易会想到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;
}