codeforces2015ICL,Finals,Div.1#J Ceizenpok’s formula 扩展Lucas定理 扩展CRT

默默敲了一个下午,终于过了,

题目传送门

 

扩展Lucas是什么,就是对于模数p,p不是质数,但是不大,如果是1e9这种大数,可能没办法,

对于1000000之内的数是可以轻松解决的。

 

题解传送门

 

代码完全手写,直接写了扩展的中国剩余定理(普通的不会写)

题意:给你n,m,p 求C(n,m)%p

  1 #include<cstring>
  2 #include<cmath>
  3 #include<cstdio>
  4 #include<iostream>
  5 #include<algorithm>
  6 
  7 #define ll long long
  8 #define N 27
  9 using namespace std;
 10 inline ll read()
 11 {
 12     ll x=0,f=1;char ch=getchar();
 13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
 14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 
 18 ll n,m,p,ans,Modulo;
 19 ll prime[N],num[N],mod[N];
 20 int tot;
 21 
 22 void get_factor(ll p)
 23 {
 24     int up=(int)sqrt(p);
 25     for (int i=2;i<=up;i++)
 26     {
 27         if (p%i==0)
 28         {
 29             prime[++tot]=i,mod[tot]=1;
 30             while(p%i==0)
 31             {
 32                 p/=i;
 33                 num[tot]++;
 34                 mod[tot]*=i;
 35             }
 36         }
 37     }
 38     if (p>1) num[++tot]=1,prime[tot]=mod[tot]=p;
 39 }
 40 ll fast_pow(ll a,ll b,ll mod)
 41 {
 42     ll ans=1;
 43     while(b)
 44     {
 45         if (b&1) (ans*=a)%=mod;
 46         (a*=a)%=mod;
 47         b>>=1;
 48     }
 49     return ans;
 50 }
 51 ll Recursion(ll n,ll x)
 52 {
 53     if (!n) return 1;
 54     ll dw=1;
 55     for (ll i=1;i<=mod[x];i++)
 56         if (i%prime[x]!=0) (dw*=i)%=mod[x];
 57     ll res=fast_pow(dw,n/mod[x],mod[x]);
 58     for (ll i=n/mod[x]*mod[x]+1;i<=n;i++)
 59         if (i%prime[x]!=0) (res*=i%mod[x])%=mod[x];
 60     return (res*Recursion(n/prime[x],x))%mod[x];    
 61 }
 62 void Ex_gcd(ll a,ll b,ll &x,ll &y)
 63 {
 64     if (!b)
 65     {
 66         x=1,y=0;
 67         return;
 68     }
 69     else
 70     {
 71         Ex_gcd(b,a%b,x,y);
 72         ll t=x;x=y;y=t-a/b*y;
 73     }
 74 }
 75 ll Inv(ll a,ll b)
 76 {
 77     ll x,y;
 78     Ex_gcd(a,b,x,y);
 79     if (x<0) x+=b;
 80     return x;
 81 }
 82 ll get_combination(ll x)
 83 {
 84     ll ans=Recursion(n,x),k=0;
 85     for (ll i=n;i;i/=prime[x]) k+=i/prime[x];
 86     for (ll i=m;i;i/=prime[x]) k-=i/prime[x];
 87     for (ll i=n-m;i;i/=prime[x]) k-=i/prime[x];
 88     ans*=fast_pow(prime[x],k,mod[x]);
 89     ans%=mod[x];
 90     ll res1=Recursion(m,x),res2=Recursion(n-m,x);
 91     ans*=Inv(res1,mod[x]),ans%=mod[x];
 92     ans*=Inv(res2,mod[x]),ans%=mod[x];
 93     return ans;
 94 }
 95 void combine(ll &a,ll &b,ll c,ll d)
 96 {
 97     ll inv=Inv(b,d)*(c-a)%d;
 98     a=inv*b+a,b=b*d,a%=b;
 99 }
100 int main()
101 {
102     freopen("fzy.in","r",stdin);
103     freopen("fzy.out","w",stdout);
104     
105     n=read(),m=read(),p=read();
106     get_factor(p);
107     ans=get_combination(1),Modulo=mod[1];
108     for (int i=2;i<=tot;i++)
109     {
110         ll res=get_combination(i),new_mod=mod[i];
111         combine(ans,Modulo,res,new_mod);
112     }
113     printf("%lld\n",(ans%Modulo+Modulo)%Modulo);
114 }

 

posted @ 2018-03-23 17:39  Kaiser-  阅读(392)  评论(1编辑  收藏  举报