SPOJ - NUMTRYE

测试了Miller_Rabin和pollard_rho

题目里这个g(n)是有结论的,但我搞不太懂

最后f(n)/g(n) = (p1 + 1)(p2 + 1)...(pk + 1)

 

  1 #include <cstdio>
  2 #include <time.h>
  3 #include <algorithm>
  4 #include <cstring>
  5 #define MOD 1000000007        
  6 using namespace std;
  7 typedef long long LL;
  8 
  9 const int S = 8;
 10 
 11 LL mul(LL a, LL b, LL c) {
 12     a %= c;
 13     b %= c;
 14     LL res = 0;
 15     while (b) {
 16         if (b & 1) {
 17             res += a;
 18             if (res > c) res -= c;
 19         }
 20         a <<= 1;
 21         if (a > c) a -= c;
 22         b >>= 1;
 23     }
 24     return res;
 25 }
 26 
 27 LL QP(LL x, LL n, LL p) {
 28     LL res = 1;
 29     x %= p;
 30     while (n) {
 31         if (n & 1) res = mul(res, x, p);
 32         x = mul(x, x, p);
 33         n >>= 1;
 34     }
 35     return res;
 36 }
 37 
 38 bool ck(LL a, LL n, LL x, LL t) {
 39     LL res = QP(a, x, n);
 40     LL last = res;
 41     for (int i = 1; i <= t; i++) {
 42         res = mul(res, res, n);
 43         if (res == 1 && last != 1 && last != n - 1) return true;
 44         last = res;
 45     }
 46     if (res != 1) return true;
 47     else return false;
 48 }
 49 
 50 bool Miller_Rabin(LL n) {
 51     if (n < 2) return false;
 52     if (n == 2) return true;
 53     if ( (n & 1) == 0) return false;
 54     LL x = n - 1;
 55     LL t = 0;
 56     while ((x & 1) == 0) {x >>= 1; t++;}
 57     srand(time(NULL));
 58     for (int i = 0; i < S; i++) {
 59         LL a = rand() % (n - 1) + 1;
 60         if (ck(a, n, x, t)) return false;
 61     }
 62     return true;
 63 }
 64 
 65 LL fact[100];
 66 int tol;
 67 
 68 LL gcd(LL a, LL b) {
 69     LL t;
 70     while (b) {
 71         t = a;
 72         a = b;
 73         b = t % b;
 74     }
 75     if (a >= 0) return a;
 76     else return -a;
 77 }
 78 
 79 
 80 LL pollard_rho(LL x, LL c) {
 81     LL i = 1, k = 2;
 82     srand(time(NULL));
 83     LL x0 = rand() % (x - 1) + 1;
 84     LL y = x0;
 85     while (1) {
 86         i++;
 87         x0 = (mul(x0, x0, x) + c) % x;
 88         LL d = gcd(y - x0, x);
 89         if (d != 1 && d != x) return d;
 90         if (y == x0) return x;
 91         if (i == k) {y = x0; k += k;}
 92     }
 93 }
 94 
 95 void findfac(LL n, int k) {
 96     if (n == 1) return;
 97     if (Miller_Rabin(n)) {
 98         fact[tol++] = n;
 99         return;
100     }
101     LL p = n;
102     int c = k;
103     while (p >= n) p = pollard_rho(p, c--);
104     findfac(p, k);
105     findfac(n / p, k);
106 }
107 
108 int main() {
109     
110     int T;
111     LL n;
112     scanf("%d", &T);
113     while (T--) {
114         scanf("%lld", &n);
115         if (Miller_Rabin(n)) {
116             tol = 1; fact[0] = n;
117         } else {
118             tol = 0;
119             findfac(n, 107);
120         }
121         sort(fact, fact + tol);
122         tol = unique(fact, fact + tol) - fact;
123         LL ans = 1;
124         for (int i = 0; i < tol; i++) {
125             ans = ans * (fact[i] + 1) % MOD;
126         }
127         printf("%lld\n", ans);
128     }    
129     
130 
131     return 0;
132 }

 

转载于:https://www.cnblogs.com/xFANx/p/9477922.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值