BZOJ 5330 Luogu P4607 [SDOI2018] Anti-palindromic sequence (inversion Mobius, Pollard Rho algorithm)

Topic Link

(BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330
(Luogu) https://www.luogu.org/problem/P4607

answer

First observation of some properties.
A number of different palindrome string strings nature can produce rotation? Then multiple cycles.
However, there is a special case, is the length of palindromic sequence is an even number \ (SS ^ = A ^ R & lt Rss Rss ... ^ SS ^ R & lt \) ( \ (S ^ R & lt \) represents \ (S \) of the reverse ), if the number of bits exactly equal to half the rotation cycle will be generated \ (a '= S ^ ^ Rss Rss Rs of ^ ... ^ Rs of S \) , which is another palindromic sequence, thus re-count!
So we venture to guess, let \ (a \) in the period \ (T \) , then when \ (T \) the contribution of the answer is even as \ (\ FRAC {T} {2} \) , otherwise, \ (T \) .
a simple proof is that the string \ (a \) rotation \ (D \) position and rotation \ (Td \) bits of the resulting string Reverse each other, if the palindromic sequence obtained, then \ (D = Td \) .

The problem we now simplified: set length \ (n-\) character set is \ (m \) period \ (T \) a palindromic sequence has \ (g (T) \) a request is \ (\ sum_ {D |} n-G (D) H (D) \) , where \ (h (d) \) contribution.
Now consider how budget cycle for the \ (T \) palindromic sequence: Let \ (G (T) \) indicates the number palindrome string that satisfies \ (T \) is its period (but not the minimum period, that period is \ (T \) factor), the \ (G (T) = m ^ {\ lceil \ FRAC {T} {2} \ rceil} \) .
, and have \ (G (T) = \ sum_ {d | T} G (D) \) , can be obtained by a Mobius inversion \ (g (T) = sum_ {d | T} \ mu (\ frac {T} {d}) G (d) \) .
then enumerated directly seeking the bare factor can be obtained from 54 to 60 minutes (of course, also be \ (G (T) = G (T) - \ sum_ {D |} G T (D) \) , but due to the complexity of this an inferior only 30-36 minutes, is expected to score in the official explanations given)

When \ (n \ le 10 ^ { 18} \) when, \ (n-\) number submultiple \ (D (n-) \ Le 103680 \) .
Push formula: \ (\ sum_ {D |} n- \ sum_ {d '| d} G (d') \ mu (\ frac {d} {d '}) h (d) = \ sum_ {d | n} \ sum_ {d' | \ frac {n} { d}} G (d) \
mu (d ') h (dd') \) observation equation, when the \ (D \) is odd \ (\ frac {n} { d} \) is an even number, each It is odd and an even make a pair, and the (\ MU \) \ opposite values. This situation therefore contribute to answer \ (0 \) .
In other cases, must satisfy \ (H (dd ') = H (D) D' \) , i.e., \ (\ sum_ {d | n } G ( d) h (d) \ sum_
{d '| \ frac {n} {d}} d' \ mu (d ') \) considered \ (\ sum_ {d | n } d \ mu (d) \) of Clinical significance, easy to get the original formula is equal to \ (\ sum_ {D | n-} G (D) H (D) \ prod_ {P | \ FRAC {n-} {D}} (. 1-P) \) , where \ ( p \) is a prime
DFS all prime factors can be.

Time complexity \ (O (n-^ {\ FRAC {. 1} {. 4}} \ log n-+ D (n-) \ log n-) \) , where \ (d (n) \) of \ (n-\) of divisor number.

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<vector>
#define llong long long
#define pll pair<llong,llong> 
#define mkpr make_pair
using namespace std;

const int N = 103680;
vector<pll> pfac;
llong P;

llong quickmul(llong x,llong y,llong mod=P)
{
    return (x%mod)*(y%mod)%mod;
}
llong quickpow(llong x,llong y,llong mod=P)
{
    llong cur = x,ret = 1ll;
    for(int i=0; y; i++)
    {
        if(y&(1ll<<i)) {ret = quickmul(ret,cur,mod)%mod; y-=(1ll<<i);}
        cur = quickmul(cur,cur,mod);
    }
    return ret;
}

namespace Pollard_Rho
{
    const int N = 15;
    const int LGM = 64;
    llong fc[LGM+2];
    llong a[N+2];
    llong m;
    int n;
    llong ans;
    llong quickmul(llong x,llong y,llong mod=P)
    {
        llong tmp=(x*y-(llong)((long double)x/mod*y+1.0e-8)*mod)%mod;
        return tmp<0 ? tmp+mod : tmp;
    }
    llong quickpow(llong x,llong y,llong mod=P)
    {
        llong cur = x,ret = 1ll;
        for(int i=0; y; i++)
        {
            if(y&(1ll<<i)) {ret = quickmul(ret,cur,mod)%mod; y-=(1ll<<i);}
            cur = quickmul(cur,cur,mod);
        }
        return ret;
    }
    llong gcd(llong x,llong y) {return y==0 ? x : gcd(y,x%y);}
    llong absl(llong x) {return x>=0 ? x : -x;}
    llong ssrand(llong x,llong c,llong y) {return (quickmul(x,x,y)+c)%y;}
    bool Miller_Rabin(llong x)
    {
        if(x==1) return false;
        if(x==2) return true;
        if((x&1)==0) return false;
        llong y = x-1,t = 0ll;
        while((y&1)==0) y>>=1,t++;
        for(int i=1; i<=5; i++)
        {
            llong bas = rand()%(x-1)+1;
            llong cur = quickpow(bas,y,x);
            for(int j=1; j<=t; j++)
            {
                llong tmp = quickmul(cur,cur,x);
                if(tmp==1 && cur!=1 && cur!=x-1) return false;
                cur = tmp;
            }
            if(cur!=1) return false;
        }
        return true;
    }
    llong pollard_rho(llong x,llong c)
    {
        llong i = 1,k = 2;
        llong y = rand()%(x-1)+1; llong t = y;
        while(true)
        {
            i++;
            y = ssrand(y,c,x);
            llong d = gcd(absl(t-y),x);
            if(d>1 && d<x) return d;
            if(t==y) return x;
            if(i==k)
            {
                t = y;
                k<<=1;
            }
        }
    }
    void factorize(llong x,llong c)
    {
        if(x==1) return;
        if(Miller_Rabin(x))
        {
            n++; fc[n] = x;
            return;
        }
        llong p = x,k = c;
        while(p>=x) p = pollard_rho(p,c--);
        factorize(p,k); factorize(x/p,k);
    }
    void Factorize(llong _m)
    {
        m = _m;
        n = 0;
        factorize(m,120);
        sort(fc+1,fc+n+1);
        pfac.clear();
        for(int i=1; i<=n; i++)
        {
            if(fc[i]==fc[i-1]) {pfac[pfac.size()-1].second++;}
            else {pfac.push_back(mkpr(fc[i],1));}
        }
    }
}

llong n,m;
llong ans;

void dfs(int pos,llong x,llong coe)
{
    if(pos==pfac.size())
    {
        if((x&1ll) && (!((n/x)&1ll))) {return;}
        llong tmp = quickmul(coe,quickmul(quickpow(m,(x+1)>>1),(x&1)?x:(x>>1)));
        ans = (ans+tmp)%P;
        return;
    }
    for(int i=0; i<=pfac[pos].second; i++)
    {
        dfs(pos+1,x,i==pfac[pos].second?coe:quickmul(coe,(P+1-pfac[pos].first%P)));
        x = x*pfac[pos].first;
    }
}

int main()
{
    srand(time(NULL));
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&n,&m,&P);
        Pollard_Rho::Factorize(n);
//      for(int i=0; i<pfac.size(); i++) printf("(%lld,%lld) ",pfac[i].first,pfac[i].second); puts("");
        ans = 0ll;
        dfs(0,1ll,1ll);
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11528825.html