了然自闭。话说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 ",(ans+mod)%mod); } return 0; }