zoukankan      html  css  js  c++  java
  • CF 1033 D. Divisors

    D. Divisors

    http://codeforces.com/contest/1033/problem/D

    题意:

      给n个(n<=500)个数,($a_i <= 2 imes 10 ^ {18}$),每个数的因数个数在[3,5]内。$a = prodlimits_{i=1}^na_i$,求a的因数个数。

    分析:

      首先有一个结论:一个数x的质因数分解后为:$x = p_1^{a_1}p_2^{a_2}...p_k^{a_k}$ 那么它的因数个数就是 $(a_1 + 1) imes (a_2 + 1) imes ... imes (a_k + 1)$。

      于是这道题就可以求出每个质因数的个数,然后将指数+1相乘即可。

      但是$a_i$太大了,无法直接求质因数。

      因为每个数的因数个数在[3,5]范围内,所以根据上面的结论,可以知道每个数的质因数分解只有四种形式:$pq, p^2, p^3,p^4$。后三种直接二分就能算出其质因数,用map记录每个质因数的指数。

      对于第一种,直接求质因数是不可能的了,考虑能否不求质因数,而计算答案。首先对于所有数二分,如果不能分成后三种,那么将其记录到b数组中。b中的一个数拆成第一种形式后,p和q,在map都没出现过,那么我们可以知道它的贡献就是(2*2)了(不考虑后面的)。如果p和q中有一个出现过了,我们必须要合并他们的幂。

      如何合并幂:枚举b[i],枚举a数组中的所有数,求gcd,如果1<gcd<b[i],那么可以说明b[i]和a[j]分解后的都有gcd,(b[i]=pq,gcd=p或者q)。

      对于剩下的数,每一个分解后的质数都是还未出现过,直接计算答案。

    代码: 

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 #include<set>
     8 #include<vector>
     9 #include<queue>
    10 #include<map>
    11 #define fi(s) freopen(s,"r",stdin);
    12 #define fo(s) freopen(s,"w",stdout);
    13 using namespace std;
    14 typedef long long LL;
    15 
    16 inline LL read() {
    17     LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    19 }
    20 
    21 const int N = 505;
    22 const int mod = 998244353;
    23 const LL INF = 9e18;
    24 
    25 LL a[N], b[N], c[N];
    26 map<LL,int> f;
    27 LL Sqrt(LL x,int k) {
    28     LL l = 1, r; // 虽然现在的l,r在int范围内,但是也要开longlong!!!!!
    29     if (k == 2) r = 1414213563;
    30      if (k == 3) r = 1259922;
    31      if (k == 4) r = 37607;
    32     while (l <= r) {
    33         LL mid = (l + r) >> 1;
    34         LL t = 1;
    35         for (int i=1; i<=k; ++i) t = 1ll * t * mid;
    36         if (t == x) return mid;
    37         else if (t > x) r = mid - 1;
    38         else l = mid + 1;
    39     }
    40     return -1;
    41 }
    42 LL gcd(LL a,LL b) {
    43     return b == 0 ? a : gcd(b, a % b);
    44 }
    45 int main() { 
    46     int n = read();
    47     for (int i=1; i<=n; ++i) a[i] = read();
    48 
    49     for (int i=1; i<=n; ++i) {
    50         bool flag = 0;
    51         for (int k=4; k>=2; --k) { // 从大到小!!! 
    52             LL p = Sqrt(a[i], k);
    53             if (p != -1) { f[p] += k; flag = 1; break; }
    54         }
    55         if (!flag) b[i] = a[i];
    56     }    
    57     for (int i=1; i<=n; ++i) {
    58         if (!b[i]) continue;
    59         bool flag = 0;
    60         for (int j=1; j<=n; ++j) {
    61             if (i == j) continue;
    62             LL d = gcd(b[i], a[j]);
    63             if (d != 1 && d != b[i]) {
    64                 flag = 1; f[d] ++; f[b[i] / d] ++; break;
    65             }
    66         }
    67         if (!flag) c[i] = b[i];
    68     }
    69     LL ans = 1;
    70     for (int i=1; i<=n; ++i) {
    71         if (!c[i]) continue;
    72         LL cnt = 2;
    73         for (int j=1; j<=n; ++j) 
    74             if (i != j && c[i] == c[j]) cnt ++, c[j] = 0;
    75         cnt = cnt * cnt % mod;
    76         ans = ans * cnt % mod;
    77     }
    78     map<LL,int> :: iterator it;
    79      for (it=f.begin(); it!=f.end(); it++) 
    80          ans = (ans * (it->second + 1)) % mod;
    81 //    for (auto p: f) ans = (ans * (p.second + 1)) % mod;
    82     cout << ans;
    83      fflush(stdout);
    84     return 0;
    85 }
  • 相关阅读:
    Some day some time we will do
    qemu-img 的使用
    虚拟化qemu-img的简单用法。
    linux 后台执行命令
    C#向服务器上传文件问题
    Canvas保存为图片
    一个Sql备注
    fabric Clone
    Js 正则获取Html元素
    Graphic 完成文字缩放
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9754334.html
Copyright © 2011-2022 走看看