• bzoj1319


    数论

    这个幂指数很难搞,那么我们取个log

    去取log得有底数,那么自然这个底数能表示出所有的数

    原根满足这个性质

    那么我们求出原根,再去log

    变成k*ind(x)=ind(a) (mod phi(p))

    phi(p)=p-1

    又因为g^ind(a)=a (mod p)

    那么我们用bsgs求出ind(a)

    那么我们就要解出ind(x)的所有解,用exgcd

    然后求出最小自然数数解,然后通解是x+b*t

    那么每次加b就行了

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 5;
    int p, k, a, top;
    ll Ans[N], st[N];
    ll power(ll x, ll t)
    {
        ll ret = 1;
        for(; t; t >>= 1, x = x * x % p) if(t & 1) ret = ret * x % p;
        return ret;
    }
    int find_root(int p)
    {
        if(p == 2) return 1;
        int tmp = p - 1;
        for(int i = 2; i * i <= p; ++i) if(tmp % i == 0)
        {
            st[++top] = i; 
            while(tmp % i == 0) tmp /= i;
        }
        if(tmp != 1) st[++top] = tmp;
        for(int g = 2; g < p; ++g) 
        {
            bool flag = true;
            for(int j = 1; j <= top; ++j)        
            {
                if(power(g, (p - 1) / st[j]) == 1) 
                {
                    flag = false;
                    break;
                }
            }
            if(flag) return g;
        }
        return -1;
    }
    int bsgs(int a, int b, int p) 
    {
        map<ll, int> mp;
        int m = sqrt(p);
        ll x = 1, pw = power(a, m);
        for(int i = 0; i <= m; ++i) 
        {
            mp[x] = i * m;
            x = x * pw % p;
        }
        x = 1;
        for(int i = 0; i < m; ++i)
        {
            ll tmp = power(x, p - 2) * b % p;
            if(mp.find(tmp) != mp.end()) return mp[tmp] + i;
            x = x * a % p;
        }
    }
    ll exgcd(ll a, ll b, ll &x, ll &y) 
    {
        if(b == 0) 
        {
            x = 1;
            y = 0;
            return a;
        }
        int ret = exgcd(b, a % b, y, x);
        y -= (a / b) * x;
        return ret;
    }
    int main()
    {
        cin >> p >> k >> a;
        ll g = find_root(p), c = bsgs(g, a, p), b = p - 1, x, y, gcd = exgcd(k, b, x, y);
        if(c % gcd != 0) return puts("0"), 0;
        c /= gcd;
        b /= gcd;
        k /= gcd;
        x = (x * c % b + b) % b;
        while(x < p) 
        {
            Ans[++Ans[0]] = power(g, x);
            x += b;
        } 
        sort(Ans + 1, Ans + Ans[0] + 1);
        printf("%d
    ", Ans[0]);
        for(int i = 1; i <= Ans[0]; ++i) printf("%lld
    ", Ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    hdu 1716 排列
    codevs 2597 团伙
    创建了一个静态数组,越界访问为什么不报错
    hdu 2083 简易版之最短距离
    hdu 2073 无限的路
    hdu 2060 Snooker
    hdu 1877
    hdu 1042 N!
    hdu 1799 循环多少次?
    百练:2972 确定进制
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8067049.html
Copyright © 2020-2023  润新知