BZOJ 1951 [SDOI2010]古代猪文 (组合数学+欧拉降幂+中国剩余定理)

题目大意:求$G^{\sum_{m|n} C_{n}^{m}}\;mod\;999911659\;$的值$(n,g<=10^{9})$

并没有想到欧拉定理..

999911659是一个质数,所以$\varphi(p)=p-1$

利用欧拉定理,降幂化简式子$G^{\sum_{m|n} C_{n}^{m}\;mod\;\varphi(p)}$

这样,指数部分可以用$Lucas$+中国剩余定理求解

然而..$G>10^9$很大,可能和模数$999911659$不互质!所以质数要额外加上$\varphi(p)$

  1 #include <map>
  2 #include <queue>
  3 #include <cmath>
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <algorithm>
  7 #define N 10100
  8 #define ull unsigned long long 
  9 #define ll long long
 10 #define maxn 36000
 11 using namespace std;
 12 
 13 ll n,g;
 14 const ll m[]={2,3,4679,35617};
 15 
 16 ll qpow(ll x,ll y,const ll &mod){
 17     ll ans=1;
 18     while(y){
 19         if(y&1) ans=(ans*x)%mod;
 20         x=(x*x)%mod,y>>=1;
 21     }return ans;
 22 }
 23 namespace excrt{
 24 ll exgcd(ll a,ll b,ll &x,ll &y){
 25     if(!b) {x=1,y=0;return a;}
 26     ll ans=exgcd(b,a%b,x,y);
 27     ll t=x;x=y,y=t-a/b*y;
 28     return ans;
 29 }
 30 ll qadd(ll x,ll y,const ll &mod){
 31     ll ans=0;
 32     while(y){
 33         if(y&1) ans=(ans+x)%mod;
 34         x=(x+x)%mod,y>>=1;
 35     }return ans;
 36 }
 37 ll ans=0,M=1;
 38 void insert(ll A,ll B)
 39 {
 40     ll a=A,b=B,c=(a-ans%b+b)%b,x,y,g;
 41     g=exgcd(M,b,x,y);b/=g;
 42     //if(c/g!=0) return;
 43     //x=qadd(x,c/g,b);
 44     x=x*(c/g)%b;
 45     ans+=x*M,M*=b,ans=(ans%M+M)%M;
 46 }
 47 };
 48 int son[N],d[N],ps[N],num,cnt;
 49 namespace calc{
 50 ll mul[maxn+100],inv[maxn+100],minv[maxn+100];
 51 void Pre(const ll &mo)
 52 {
 53     mul[0]=mul[1]=inv[0]=inv[1]=minv[0]=minv[1]=1;
 54     for(int i=2;i<mo;i++){
 55         mul[i]=mul[i-1]*i%mo;
 56         inv[i]=1ll*(mo-mo/i)*inv[mo%i]%mo;
 57         minv[i]=minv[i-1]*inv[i]%mo;
 58     }
 59 }
 60 ll C(ll a,ll b,const ll &mo)
 61 {return mul[a]*minv[b]%mo*minv[a-b]%mo;}
 62 ll Lucas(ll a,ll b,const ll &mo)
 63 {
 64     if(b>a) return 0;
 65     if(a<mo&&b<mo) return C(a,b,mo);
 66     return Lucas(a/mo,b/mo,mo)*Lucas(a%mo,b%mo,mo)%mo;
 67 } 
 68 ll solve(const ll &mo)
 69 {
 70     for(int i=2;i<mo;i++)
 71         mul[i]=inv[i]=minv[i]=0;
 72     Pre(mo);ll ans=0;
 73     for(int i=1;i<=cnt;i++)
 74         (ans+=Lucas(n,son[i],mo))%=mo;
 75     return ans;
 76 }
 77 };
 78 void dfs_son(int i,ll s)
 79 {
 80     if(i>num) {son[++cnt]=s;return;}
 81     for(int j=0;j<=d[i];j++)
 82         dfs_son(i+1,s),s*=ps[i];
 83 }
 84 void get_son(ll a)
 85 {
 86     int sq=sqrt(a);
 87     for(int i=2;i<=sq;i++)
 88     if(a%i==0){
 89         ps[++num]=i;
 90         while(a%i==0) 
 91             d[num]++,a/=i;
 92     }
 93     if(a!=1)
 94         ps[++num]=a,d[num]++;
 95     dfs_son(1,1);
 96 }
 97 const ll smod=999911659;
 98 
 99 int main()
100 {
101     scanf("%lld%lld",&n,&g);
102     get_son(n);
103     for(int i=0;i<4;i++)
104     {
105         ll ans=calc::solve(m[i]);
106         excrt::insert(ans,m[i]);
107     }
108     ll pw=excrt::ans;
109     ll ans=qpow(g,pw+smod-1,smod);
110     printf("%lld\n",ans);
111     return 0;
112 }

 

posted @ 2018-11-08 14:26  guapisolo  阅读(237)  评论(0编辑  收藏  举报