BZOJ 2142: 礼物

模非素数下的排列组合,简直凶残

调着调着就过了= =

都不知道怎么过的= =

直接上链接http://hi.baidu.com/aekdycoin/blog/item/147620832b567eb40df4d258.html

CODE:

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

#include<cmath>

using namespace std;

typedef long long ll;

ll a[3][50],pri[50],M[50],t[50];

ll ex_gcd(ll a,ll b,ll &x,ll &y) {

if (b==0)  {x=1,y=0 ;return a;}

ex_gcd(b,a%b,x,y);

x=x-a/b*y;

swap(x,y);

return 0;

}

ll p;

int l,sum[50];

int fen(int p){

for (int i=2;i<=sqrt(p);i++) {

if (p%i==0) { 

pri[++l]=i;

while (p%i==0) {

sum[l]++;

p/=i;

}

}

}

if (p>1) {pri[++l]=p;sum[l]=1;}

return 0;

}

ll power(ll x,ll y,ll mod){

if (y==0) return 1;

ll ans=power(x,y>>1,mod);

ans=ans*ans%mod;

if (y&1) ans=ans*x%mod;

return ans;

}

ll f[100101],cnt;

ll calcfac(ll n,ll p,ll pi){

if (n<pi) return f[n];

// printf("%lld %lld",pi,pri[1]);

ll seg=n/p,rem=n%p;

ll ret=power(f[p-1],seg,p);

ret=ret*f[rem]%p;

cnt+=n/pi;

ret=ret*calcfac(n/pi,p,pi)%p;

return ret;

}

ll china(ll *a,ll *b) {

ll tem,ans=0;

for (int i=2;i<=l;i++) {

ll x,y;

ex_gcd(b[i-1],b[i],x,y);

b[i]=b[i]*b[i-1];

a[i]=((x*(a[i]-a[i-1])*b[i-1]+a[i-1])%b[i]+b[i])%b[i];

}

return a[l];

}

ll b[51];

ll c(int n,int m){

for (int i=1;i<=l;i++) {

ll p=1;

for (int j=1;j<=sum[i];j++) p*=pri[i];

f[0]=1;

for (int j=1;j<p;j++) {

f[j]=f[j-1];

if (j%pri[i]==0) continue;

f[j]=(f[j]*j)%p;

}

cnt=0;ll ans,tem;

a[1][i]=calcfac(n,p,pri[i]);

tem=cnt;cnt=0;

a[2][i]=calcfac(m,p,pri[i]);

printf("%lld\n",pri[1]);

a[3][i]=calcfac(n-m,p,pri[i]);

cnt=tem-cnt;

a[2][i]=a[3][i]*a[2][i]%p;

ex_gcd(a[2][i],p,ans,tem);

ans=(ans%p+p)%p;

a[1][i]=a[1][i]*ans%p*power(pri[i],cnt,p)%p;

b[i]=p;

}

return (china(a[1],b));

}

ll te[8];

int main(){

ll n,m;

ll tmp=0;

scanf("%lld %lld %lld",&p,&n,&m);

for (int i=1;i<=m;i++) {

scanf("%lld",&te[i]);

tmp+=te[i];

}

if (tmp>n) {printf("Impossible");return 0;}

fen(p);

for (int i=1;i<=l;i++) printf("%lld %lld\n",pri[i],sum[i]); 

ll ans=1;

for (int i=1;i<=m;i++) {

ans=ans*c(n,te[i])%p;

n-=te[i];

// if (ans==0) {printf("%d\n",0);return 0;}

printf("\n\n");

}

printf("%lld",ans);

return 0;

}


posted @ 2014-10-05 22:09  New_Godess  阅读(196)  评论(0编辑  收藏  举报