zoukankan      html  css  js  c++  java
  • bzoj 1420 Discrete Root

    题目传送门

      戳我来传送

    题目大意

      给定$k, p, a$,求$x^{k}equiv a pmod{p}$在模$p$意义下的所有根。

      考虑模$p$下的某个原根$g$。

      那么$x  = g^{ind_{g}x}, a = g^{ind_{g}a}$。

      所以原方程转化为$g^{kcdot ind_{g}x}equiv g^{ind_{g}a} pmod{p}$。

      所以方程等价于$kcdot ind_{g}x equiv ind_{g}a pmod{varphi(p)}$。

      用exgcd解出$ind_{g}x$的所有可能的解,再用快速幂算出$x$即可。

    Code

      1 /**
      2  * bzoj     
      3  * Problem#1420
      4  * Accepted
      5  * Time: 44ms
      6  * Memory: 2032k 
      7  */
      8 #include <bits/stdc++.h>
      9 #include <ext/pb_ds/hash_policy.hpp>
     10 #include <ext/pb_ds/assoc_container.hpp>
     11 using namespace std;
     12 using namespace __gnu_pbds;
     13 typedef bool boolean;
     14 
     15 typedef class HashMap {
     16     private:
     17         static const int M = 46666; 
     18     public:
     19         int ce;
     20         int h[M], key[M], val[M], next[M];
     21         
     22         HashMap() {    }
     23         
     24         void insert(int k, int v) {
     25             int ha = k % M;
     26             for (int i = h[ha]; ~i; i = next[i])
     27                 if (key[i] == k) {
     28                     val[i] = v;
     29                     return;
     30                 }
     31             ++ce, key[ce] = k, val[ce] = v, next[ce] = h[ha], h[ha] = ce;
     32         }
     33         
     34         int operator [] (int k) {
     35             int ha = k % M;
     36             for (int i = h[ha]; ~i; i = next[i])
     37                 if (key[i] == k)
     38                     return val[i];
     39             return -1;
     40         }
     41         
     42         void clear() {
     43             ce = -1;
     44             memset(h, -1, sizeof(h));
     45         }
     46 }HashMap; 
     47 
     48 void exgcd(int a, int b, int& d, int& x, int& y) {
     49     if (!b)
     50         d = a, x = 1, y = 0;
     51     else {
     52         exgcd(b, a % b, d, y, x);
     53         y -= (a / b) * x;
     54     }
     55 }
     56 
     57 int qpow(int a, int pos, int p) {
     58     int pa = a, rt = 1;
     59     for ( ; pos; pos >>= 1, pa = pa * 1ll * pa % p)
     60         if (pos & 1)
     61             rt = rt * 1ll * pa % p;
     62     return rt;
     63 }
     64 
     65 int inv(int a, int n) {
     66     int d, x, y;
     67     exgcd(a, n, d, x, y);
     68     return (x < 0) ? (x + n) : (x);
     69 }
     70 
     71 int p, k, a;
     72 int g;
     73 
     74 inline void init() {
     75     scanf("%d%d%d", &p, &k, &a);
     76 }
     77 
     78 HashMap mp;
     79 int ind(int a, int b, int p) {
     80     mp.clear();
     81     int cs = sqrt(p - 0.5), ac = qpow(a, cs, p), iac = b * 1ll * inv(ac, p) % p, pw = 1;
     82     for (int i = cs - 1; ~i; i--)
     83         iac = iac * 1ll * a % p, mp.insert(iac, i);
     84     for (int i = 0; i < p; i += cs, pw = pw * 1ll * ac % p)
     85         if (~mp[pw])
     86             return mp[pw] + i;
     87     return -1;
     88 }
     89 
     90 int top = 0;
     91 int fac[50];
     92 void getfactors(int x) {
     93     for (int i = 2; i * i <= x; i++) {
     94         if (!(x % i)) {
     95             fac[++top] = i;
     96             while (!(x % i))    x /= i; 
     97         }
     98     }
     99     if (x != 1)    fac[++top] = x;
    100 }
    101 
    102 boolean isroot(int x) {
    103     int pos = p - 1;
    104     for (int i = 1; i <= top; i++)
    105         if (qpow(x, pos / fac[i], p) == 1)
    106             return false;
    107     return true;
    108 }
    109 
    110 inline void solve() {
    111     if (p == 1 || !a) {
    112         printf("1
    0");
    113         return;
    114     }
    115     if (p == 2)
    116         g = 1;
    117     else {
    118         getfactors(p - 1);
    119         for (g = 2; !isroot(g); g++);
    120     }
    121 
    122     int inda = ind(g, a, p), d, x, y, cir;
    123     exgcd(k, p - 1, d, x, y);
    124     if (inda % d) {
    125         puts("0");
    126         return;
    127     }
    128     cir = (p - 1) / d;
    129     x = x * 1ll * (inda / d) % cir;
    130     (x <= 0) ? (x += cir) : (0);
    131     vector<int> res;
    132     for (; x < p; x += cir)
    133         res.push_back(qpow(g, x, p));
    134     sort(res.begin(), res.end());
    135     printf("%d
    ", (signed) res.size());
    136     for (int i = 0; i < (signed) res.size(); i++)
    137         printf("%d
    ", res[i]);
    138 }
    139 
    140 int main() {
    141     init();
    142     solve();
    143     return 0;
    144 }
  • 相关阅读:
    Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)
    无向图求点割集的算法
    hdu 2121无根最小树形图要建一个虚拟节点
    hdu 1576扩展欧几里得算法
    欧几里德算法的扩展-求解不定方程
    hdu 3072 强连通+缩点+最小树形图思想
    1352 集合计数 扩展欧几里德算法
    1247 可能的路径 逆向思维
    Atcoder B
    C. Timofey and a tree 观察题 + dfs模拟
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8487455.html
Copyright © 2011-2022 走看看