当前位置: 代码迷 >> 综合 >> 求约数 hdu2601 An easy problem
  详细解决方案

求约数 hdu2601 An easy problem

热度:19   发布时间:2023-12-14 04:05:15.0

这题有两种方法,一种是直接sqrt(n)的复杂度求约数数量

还有一种当然是比较快的方法,通过质因数分解求约数数量


为什么是求约数数量呢

可以发现 n+1=(i+1)*(j+1)

 所以我们只需要求出约数的数量,就能知道i+1有多少种情况了,然后还需要讨论一下

假如n是12,约数有1,2,3,4,6,12

那么,因为是偶数个约数,所以总是两两配对的,一共有3对,所以i+1可能为1,2,3

又因为i不能为0,所以i+1不能为1,所以对数还要减小一对

所以如果约数个数为n,n为偶数,答案就等于n/2-1


如果n等于16,约数有1,2,4,8,16

那么,因为奇数个约数,所以中间一个没法配对,但是可以发现,有(n+1)/2对,除去(1,16)这一对,还有(n+1)/2-1对


综上所述,如果我们知道了约数的个数是n,那么答案就是(n+1)/2-1

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#include<functional>
#include<algorithm>using namespace std;
typedef long long LL;
typedef pair<int, int> PII;const int MX = 1e5 + 5;
const int INF = 0x3f3f3f3f;int prime[100000], vis[MX], rear = 0;
void init() {rear = 0;vis[1] = 1;for(int i = 2; i < MX; i++) {if(vis[i]) continue;prime[++rear] = i;if((LL)i * i >= MX) continue;for(int j = i * i; j < MX; j += i) {vis[j] = 1;}}
}int main() {int T;init();scanf("%d", &T);while(T--) {LL n;scanf("%I64d", &n);n++;int ans = 1, s;for(int i = 1; (LL)prime[i]*prime[i] <= n; i++) {s = 0;while(n % prime[i] == 0) {s++;n /= prime[i];}ans *= s + 1;if(n == 1) break;}if(n != 1) ans *= 2;printf("%d\n", (ans + 1)/2 - 1);}return 0;
}


  相关解决方案