bzoj5330: [Sdoi2018]反回文串

了然自闭。话说sdoi2018两道反演真的好吗

出门右拐%题解谢谢

终于见到一题不是gcd的反演了。。。

学了下大质数分解。。。注意pollard_rho随机的时候要选择一个常数c并且不再边,不然999999726000014413这种东西会让你怀疑人生

这种题暴露我的非酋属性了啊bzoj垫底loj倒数第4

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

LL quick_mul(LL A,LL p,LL mo)
{
    LL ret=0;
    while(p!=0)
    {
        if(p%2==1)ret=(ret+A)%mo;
        A=(A+A)%mo;p/=2;
    }
    return ret;
}
LL quick_pow(LL A,LL p,LL mo)
{
    LL ret=1;
    while(p!=0)
    {
        if(p%2==1)ret=quick_mul(ret,A,mo);
        A=quick_mul(A,A,mo);p/=2;
    }
    return ret;
}
//.....tool.....

bool ishs(LL a,LL t,LL mi,LL n)
{
    LL d=quick_pow(a,t,n);
    LL last=d;
    for(int i=1;i<=mi;i++)
    {
        d=quick_mul(d,d,n);
        if(d==1&&last!=1&&last!=n-1)return true;
        last=d;
    }
    if(d!=1)return true;
    return false;
}
int prr[10]={2,3,5,7,11,13,17,19,23,29};
bool miller_rabin(LL n)
{
    if(n<2)return false;
    if(n==2)return true;
    for(int i=0;i<=9;i++)
    {
        if(n==prr[i])return true;
        if(n%prr[i]==0)return false;
    }
    
    LL t=n-1;int mi=0;
    while(t%2==0)t/=2,mi++;
    for(int i=1;i<=20;i++)
    {
        LL a=rand()%(n-1)+1;
        if(ishs(a,t,mi,n))return false;
    }
    return true;
}
//~~~~~~~~~~~~~~~~~~~~~miller_rabin~~~~~~~~~~~~~~~~~~~~~~~~

LL gcd(LL a,LL b)
{
    if(a<0)a=-a;
    return a==0?b:gcd(b%a,a);
}
LL rd(LL a,LL n,LL c){return (quick_mul(a,a,n)+c)%n;}
LL pollard_rho(LL n)
{
    LL a=rand()%n,b=a,c=rand()%n;
    LL i=1,k=2;
    while(1)
    {
        a=rd(a,n,c);
        LL d=gcd(b-a,n);
        if(d!=1&&d!=n)return d;
        if(a==b)return n;
        
        i++;
        if(i==k)b=a,k*=2;
    }
}
//~~~~~~~~~~~~~~~~~~~~~~~pollard_rho~~~~~~~~~~~~~~~~~~~~~~~

int pr;LL prime[110];
void get_prime(LL n)
{
    if(n==1)return ;
    if(miller_rabin(n))
    {
        prime[++pr]=n;
        return ;
    }
    LL d=n;
    while(d>=n)
        d=pollard_rho(d);
    get_prime(d);
    get_prime(n/d);
}

//---------------------------------------------divi---------------------------------------------------------------

int plen,q[110];
LL n,m,mod,ans,p[110];
LL qquick_pow(LL A,LL p)
{
    LL ret=1;
    while(p!=0)
    {
        if(p%2==1)ret=ret*A%mod;
        A=A*A%mod;p/=2;
    }
    return ret;
}
void dfs(int k,LL d,LL pd)
{
    if(k==plen+1)
    {
        if(d%2==1&&n/d%2==0)return ;
        LL dd=quick_mul( qquick_pow(m,(d+1)/2) , (d%2==0?d/2:d) ,mod );
        ans=(ans+quick_mul(pd,dd,mod) )%mod;
        return ;
    }
    LL pd2=pd*(1-p[k]);
    for(int i=0;i<=q[k];i++)
    {
        dfs(k+1,d,i==q[k]?pd:pd2);
        d*=p[k];
    }
}

int main()
{
    srand(3458961);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&n,&m,&mod);m%=mod;
        pr=0;get_prime(n);
        sort(prime+1,prime+pr+1);
        
        plen=1;p[1]=prime[1],q[1]=1;
        for(int i=2;i<=pr;i++)
            if(p[plen]==prime[i])q[plen]++;
            else p[++plen]=prime[i],q[plen]=1;
            
        ans=0;
        dfs(1,1,1);
        printf("%lld\n",(ans+mod)%mod);
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKCqhzdy/p/10222322.html