Divisors CodeForces - 1033D(pollard_rho算法)

本文详细介绍了Pollard_rho算法在分解质因数中的应用,通过实例展示了如何利用该算法解决复杂数学问题,如计算多个大整数乘积的因数数量。代码示例清晰地说明了算法实现细节。

Divisors CodeForces - 1033D(pollard_rho算法)

题目大意

给出n个数,每个数有3到5个因数,问n个数的积有多少因数

解题思路

pollard_rho算法分解质因数,然后答案就是∏i∣a(cnt[i]+1)\prod_{i|a}(cnt[i]+1)ia(cnt[i]+1)

AC代码

#include<bits/stdc++.h>
 
using namespace std;
typedef long long LL;
const LL mod=998244353; 
namespace rho{
    const int MAXP = 1000010;
    const int BASE[] = {2, 450775, 1795265022, 9780504, 28178, 9375, 325};

    long long seq[MAXP];
    int primes[MAXP], spf[MAXP];


    long long gcd(long long a, long long b) {
        int ret = 0;
        while(a) {
            for( ; !(a & 1) && !(b & 1); ++ret, a >>= 1, b >>= 1);
            for( ; !(a & 1); a >>= 1);
            for( ; !(b & 1); b >>= 1);
            if(a < b) swap(a, b);
            a -= b;
        }
        return b << ret;
    }

    inline long long mod_add(long long x, long long y, long long m){
        return (x += y) < m ? x : x - m;
    }

    inline long long mod_mul(long long x, long long y, long long m){
        long long res = x * y - (long long)((long double)x * y / m + 0.5) * m;
        return res < 0 ? res + m : res;
    }

    inline long long mod_pow(long long x, long long n, long long m){
        long long res = 1 % m;
        for (; n; n >>= 1){
            if (n & 1) res = mod_mul(res, x, m);
            x = mod_mul(x, x, m);
        }

        return res;
    }

    inline bool miller_rabin(long long n){
        if (n <= 2 || (n & 1 ^ 1)) return (n == 2);
        if (n < MAXP) return spf[n] == n;

        long long c, d, s = 0, r = n - 1;
        for (; !(r & 1); r >>= 1, s++) {}

        for (int i = 0; primes[i] < n && primes[i] < 32; i++){
            c = mod_pow(primes[i], r, n);
            for (int j = 0; j < s; j++){
                d = mod_mul(c, c, n);
                if (d == 1 && c != 1 && c != (n - 1)) return false;
                c = d;
            }

            if (c != 1) return false;
        }
        return true;
    }

    inline void init(){
        int i, j, k, cnt = 0;

        for (i = 2; i < MAXP; i++){
            if (!spf[i]) primes[cnt++] = spf[i] = i;
            for (j = 0, k; (k = i * primes[j]) < MAXP; j++){
                spf[k] = primes[j];
                if(spf[i] == spf[k]) break;
            }
        }
    }

    long long pollard_rho(long long n){
        while (1){
            long long x = rand() % n, y = x, c = rand() % n, u = 1, v, t = 0;
            long long *px = seq, *py = seq;

            while (1){
                *py++ = y = mod_add(mod_mul(y, y, n), c, n);
                *py++ = y = mod_add(mod_mul(y, y, n), c, n);
                if((x = *px++) == y) break;

                v = u;
                u = mod_mul(u, abs(y - x), n);

                if (!u) return gcd(v, n);
                if (++t == 32){
                    t = 0;
                    if ((u = gcd(u, n)) > 1 && u < n) return u;
                }
            }

            if (t && (u = gcd(u, n)) > 1 && u < n) return u;
        }
    }

    vector <long long> factorize(long long n){
        if (n == 1) return vector <long long>();
        if (miller_rabin(n)) return vector<long long> {n};

        vector <long long> v, w;
        while (n > 1 && n < MAXP){
            v.push_back(spf[n]);
            n /= spf[n];
        }

        if (n >= MAXP) {
            long long x = pollard_rho(n);
            v = factorize(x);
            w = factorize(n / x);
            v.insert(v.end(), w.begin(), w.end());
        }

        sort(v.begin(), v.end());
        return v;
    }
}
unordered_map<LL,int> mp;
int main() {
	rho::init();
    int n;
    scanf("%d",&n);
    LL x;
    while (n--){
        scanf("%lld", &x);
        vector <long long> v = rho::factorize(x);
        for (auto x: v) mp[x]++;
    }
    LL ans=1;
    for(auto x:mp) ans=(ans*(x.second+1))%mod;
    printf("%lld\n",ans);
    return 0;
}
// 就是用6阶taylor展开算e^x,是一个的单元,和个数无关,并行算指数。 module exponent (x,clk,enable,output_exp,ack); parameter DATA_WIDTH=32; localparam taylor_iter=7; input [DATA_WIDTH-1:0] x; input clk; input enable; output reg ack; output reg [DATA_WIDTH-1:0] output_exp; reg [DATA_WIDTH*taylor_iter-1:0] divisors; // 1/6 1/5 1/4 1/3 1/2 1 1 reg [DATA_WIDTH-1:0] mult1; //is 1 in the first cycle and then the output of the second multiplication in the rest reg [DATA_WIDTH-1:0] one_or_x; //one in the first cycle and then x for the rest wire [DATA_WIDTH-1:0] out_m1; //output of the first multiplication which is either with 1 or x wire [DATA_WIDTH-1:0] out_m2; //the output of the second muliplication and the input of the first wire [DATA_WIDTH-1:0] output_add1; reg [DATA_WIDTH-1:0] out_reg; //the output of the Addition each cycle // reg enable_r; floatMult FM1 (mult1,one_or_x,out_m1); floatMult FM2 (out_m1,divisors[31:0],out_m2); floatAdd FADD1 (out_m2,out_reg,output_add1); always @ (posedge clk) begin // enable_r<=enable; if(enable==1'b0) begin one_or_x=32'b00111111100000000000000000000000; //initially 1 mult1=32'b00111111100000000000000000000000; //initially 1 out_reg=32'b00000000000000000000000000000000; //initially 0 output_exp=32'b00000000000000000000000000000000; //output zero until ack is 1 divisors=224'b00111110001010101010101010101011_00111110010011001100110011001101_00111110100000000000000000000000_00111110101010101010101010101011_00111111000000000000000000000000_00111111100000000000000000000000_00111111100000000000000000000000; ack=1'b0; // acknowledge is 0 at the beginning end else begin one_or_x=x; mult1=out_m2; //get the output of the second multiplication to multiply with x divisors=divisors>>32; //shift 32 bit to divide the out_m1 with the new number to compute the factorial out_reg=output_add1; if(divisors==224'b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) begin output_exp=output_add1; ack=1'b1; end end end endmodule 这段代码里ack为1后是一直保持吗
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值