BZOJ 3738 Ontak2013 Kapitał 数论

来源:互联网 发布:乌合之众知乎 编辑:程序博客网 时间:2024/06/11 21:43

题目大意:求C(n+m,n)去掉末尾所有的0之后的后k位

组合数取模问题……首先k<=9,所以我们考虑直接mod 10^9

将10^9分解质因数,可以得到10^9=2^9*5^9=512*1953125 这两个数都不是很大 所以直接套用组合数取模的模板

具体细节参见 2142 礼物 http://blog.csdn.net/popoqqq/article/details/39891263

消0的时候注意消掉2的时候要乘上相应5的逆元 消5同理

#include <cstdio>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>#define P1 512ll#define P2 1953125llusing namespace std;typedef long long ll;typedef pair<ll,ll> abcd;ll n,m,k;ll power1[P1+1],power2[P2+1];ll Quick_Power(ll x,ll y,ll p){    ll re=1;    while(y)    {        if(y&1) re*=x,re%=p;        x*=x,x%=p;        y>>=1;    }    return re;}abcd Plus(const abcd x,const abcd y,ll p){    return abcd(x.first*y.first%p,x.second+y.second);}abcd Minus(const abcd x,const abcd y,ll p,ll phi_p){    return abcd(x.first*Quick_Power(y.first,phi_p-1,p)%p,x.second-y.second);}abcd Find(ll x,ll p,ll p_a,ll pow[]){    ll i,temp;    if(!x) return abcd(1,0);    temp=Quick_Power(pow[p_a],x/p_a,p_a)*pow[x%p_a]%p_a;    return Plus(abcd(temp,x/p),Find(x/p,p,p_a,pow),p_a);}int main(){    int i;    power1[0]=power2[0]=1;    for(i=1;i<=P1;i++) power1[i]=power1[i-1]*(i%2?i:1)%P1;    for(i=1;i<=P2;i++) power2[i]=power2[i-1]*(i%5?i:1)%P2;    cin>>n>>m>>k;    abcd p1=Find(n+m,2,P1,power1);    p1=Minus(p1,Find(n,2,P1,power1),P1,P1/2*1);    p1=Minus(p1,Find(m,2,P1,power1),P1,P1/2*1);    abcd p2=Find(n+m,5,P2,power2);    p2=Minus(p2,Find(n,5,P2,power2),P2,P2/5*4);    p2=Minus(p2,Find(m,5,P2,power2),P2,P2/5*4);    ll temp=min(p1.second,p2.second);    ll x=p1.first*Quick_Power(2,p1.second-temp,P1)%P1*Quick_Power(205,temp,P1)%P1;    ll y=p2.first*Quick_Power(5,p2.second-temp,P2)%P2*Quick_Power(976563,temp,P2)%P2;    ll ans=(1953125*109*x+512*1537323*y)%1000000000;    cout<<setfill('0')<<setw(k)<<ans%Quick_Power(10,k,1000000001)<<endl;}


0 0
原创粉丝点击