LightOJ

题意:T(<=1e4)组数据,求对于N(<=1e12),已知N在k进制表示下末位是0,求有多少个可能的k

相当与求解每个N的因数个数减1(代表除去1进制的情况)

N=p1a1*p2a2*...*pnan,若N=m*n,那么m可表示为m=x*p1^(k), 0 <= k <= a1,

那么N的约数个数为(a1+1)(a2+1)...(an+1)

对于不大于1e12的数,若它为素数,答案恒为1;若它不为素数,那么它必然可以被不大于1e6的数整除,所以我们只需要预处理出不大于1e6的素数表即可。

计算时求出每个素数的指数,不断累乘即可。注意最后如果N!=1,说明最后剩下的是素数,所以答案再乘2.代表指数0和1两种情况(类似于求欧拉函数的过程)

复杂度的话,π(1000000)=1000000/ln(1000000)=72383,最坏情况下约7*10^(8),推车.jpg

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define INF 0x3f3f3f3f
 5 #define MOD 1000000007
 6 typedef long long LL;
 7 
 8 const int maxn = 1e6 + 10;
 9 int prime[maxn];
10 bool is_prime[maxn];
11 
12 int T;
13 LL N;
14 
15 void init() {
16     for (int i = 0; i < maxn; i++) is_prime[i] = true;
17     is_prime[0] = is_prime[1] = false;
18     for (int i = 2; i < maxn; i++) {
19         if (is_prime[i]) {
20             prime[++prime[0]] = i;
21             for (int j = i + i; j < maxn; j += i) is_prime[j] = false;
22         }
23     }
24 }
25 
26 int main() {
27     init();
28     scanf("%d", &T);
29     for (int t = 1; t <= T; t++) {
30         scanf("%lld", &N);
31         LL ans = 1;
32         for (int i = 1; i <= prime[0] && (LL)prime[i] * prime[i] <= N; i++) {
33             LL tmp = 0;
34             while (N % prime[i] == 0) {
35                 N /= prime[i];
36                 tmp++;
37             }
38             ans *= (tmp + 1);
39         }
40         if (N > 1) ans *= 2;
41         printf("Case %d: %lld
", t, ans - 1);
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/xFANx/p/7520777.html