hdu 七夕节
题目链接
题目描述
有T个样例,每个样例给定一个N,将所给N的所有因子相加求和。N的因子就是所有比N小又能被N整除的所有正整数。如12的因子有1,2,3,4,6。(T(1<=T<=500000),N(1<=N<=500000))
解题思路
这个题思路很简单,可能你首先想到了不就是从1到n进行遍历,找他的因子,再用一个变量计算因子和不就可以了么。但是我们观察到,样例个数T和给定的N都可能会很大,假如直接遍历1到N,那么时间复杂度就会很大,会导致超时。所以我们就想,怎么可以简化这个循环遍历的过程呢。
我们就可以想到,这些数字是有相关性的,比如当你遍历发现2是10的因子,那么10/2=5,5也是10的因子,这样我们就简化了循环,只需要遍历到 i * i <= N的情况。也就是如下代码:
int sum = 0;
for(int i = 1; i*i<=n; i++) {
if(n%i==0) {
sum += (i+n/i);
}
}
但是有几个小细节需要注意,比如因为题目中说,因子要小于N,那么在变量 i 循环到 1 的时候,就不能把N/1=N加进去,还有当i * i刚好为N时,我们只需要加一遍 i 就可以了,而不需要把 i 和 N/i 都加进去。所以要判断一下这两种特殊情况。
具体代码
对于我上面提到的两种特殊情况,也可以用其他的方法进行处理。
#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
int t;
scanf("%d",&t);
while(t--) {
int n;
scanf("%d",&n);
int sum = 1; //初始化sum = 1,相当于把 i = 1的情况已经处理了。
for(int i = 2; i*i<=n; i++){ //直接从2开始循环
if(i*i == n) { //特殊判断 i*i=n的情况
sum += i;
}
else if(n%i==0) {
sum += (i+n/i);
}
}
if(n==1) printf("0\n");
else {
printf("%d\n",sum);
}
}
}