礼物
Description
一年一度的圣诞节快要来到了。
每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。
不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。
小E从商店中购买了
n
件礼物,打算送给
请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。
由于方案数可能会很大,你只需要输出模
P
后的结果。
Input
输入的第一行包含一个正整数
第二行包含两个整整数
n
和
以下
m
行每行仅包含一个正整数
Output
若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模
Sample Input
100 4 2 1 2
Sample Output
12
Hint
【样例说明】
下面是对样例1的说明。
以“/”分割,“/”前后分别表示送给第一个人和第二个人的礼物编号。12种方案详情如下:
1/23 1/24 1/34
2/13 2/14 2/34
3/12 3/14 3/24
4/12 4/13 4/23
【数据规模和约定】
设 P=pc11∗pc22∗pc33∗…∗pctt , pi 为质数。
对于 100% 的数据, 1≤n≤109,1≤m≤5,1≤pcii≤105 。
Solution
令
si=∑i−1j=1wj
,则
所以我们只要求出 Cyx mod p 的值就可以了。
由CRT,我们只需求出
Cyx mod pji
,然后CRT合并即可。
所以只要求出
n! mod pji
,就万事大吉了。
由
由
所以左边可以用 1×2×3×…×(pji−1) 的幂加上暴力就可以求了。
右边的话提出一个 pi 就可以递归处理了。
最后将 Cyx 化成 a⋅pkib⋅pli 的形式,就可以求出模值了。
Code
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
#define MAXN 100000
using namespace std;
LL p,n,m,ans;
LL w[20],s[20];
LL pi[1000010],pc[1000010],cc[1000010];
LL tmp[1000010];
LL pop[1000010];
LL tott[1000010];
LL returnthing;
LL power(LL x,LL y,LL Mod){
if(y==0)return 1;
if(y==1)return x%Mod;
LL tmps=power(x,y/2,Mod);
tmps=tmps*tmps%Mod;
if(y&1)tmps=tmps*(x%Mod)%Mod;
return tmps;
}
LL jie(LL x,LL i){
if(x==0){returnthing=0;return 1;}
if(x==1){returnthing=0;return 1;}
LL A=x/pc[i],B=x%pc[i];
LL b1=power(tmp[i],A,pc[i])%pc[i];
// LL c1=A*(tott[i]+1);
LL c1=A*pc[i]/pi[i];
for(LL j=A*pc[i]+1;j<=x;j++){
if(j%pi[i]!=0)b1=b1*j%pc[i];
else{
LL ttt=j,tttottt=0;
while(ttt%pi[i]==0){ttt/=pi[i];tttottt++;}
c1+=tttottt;
b1=b1*ttt%pc[i];
}
}
b1=b1*jie(A*pc[i]/pi[i],i)%pc[i];
c1+=returnthing;
returnthing=c1;
return b1;
}
LL ex_gcd(LL x,LL y,LL &a,LL &b){
if(y==0){a=1;b=0;return x;}
LL ta,tb;
LL z=ex_gcd(y,x%y,ta,tb);
a=tb;b=ta-tb*(x/y);
return z;
}
LL work(LL x,LL y){
if(x<y||y==0)return 0;
LL now=0;
for(LL i=1;i<=pi[0];i++){
LL f;
LL A=x/pc[i],B=x%pc[i];
LL b1=power(tmp[i],A,pc[i])%pc[i];
// LL c1=A*(tott[i]+1);
LL c1=A*pc[i]/pi[i];
for(LL j=A*pc[i]+1;j<=x;j++){
if(j%pi[i]!=0)b1=b1*j%pc[i];
else{
LL ttt=j,tttottt=0;
while(ttt%pi[i]==0){ttt/=pi[i];tttottt++;}
c1+=tttottt;
b1=b1*ttt%pc[i];
}
}
b1=b1*jie(A*pc[i]/pi[i],i)%pc[i];
c1+=returnthing;
A=(x-y)/pc[i],B=(x-y)%pc[i];
LL b2=power(tmp[i],A,pc[i])%pc[i];
// LL c2=A*(tott[i]+1);
LL c2=A*pc[i]/pi[i];
for(LL j=A*pc[i]+1;j<=x-y;j++){
if(j%pi[i]!=0)b2=b2*j%pc[i];
else{
LL ttt=j,tttottt=0;
while(ttt%pi[i]==0){ttt/=pi[i];tttottt++;}
c2+=tttottt;
b2=b2*ttt%pc[i];
}
}
b2=b2*jie(A*pc[i]/pi[i],i)%pc[i];
c2+=returnthing;
A=y/pc[i],B=y%pc[i];
LL b3=power(tmp[i],A,pc[i])%pc[i];
// LL c3=A*(tott[i]+1);
LL c3=A*pc[i]/pi[i];
for(LL j=A*pc[i]+1;j<=y;j++){
if(j%pi[i]!=0)b3=b3*j%pc[i];
else{
LL ttt=j,tttottt=0;
while(ttt%pi[i]==0){ttt/=pi[i];tttottt++;}
c3+=tttottt;
b3=b3*ttt%pc[i];
}
}
b3=b3*jie(A*pc[i]/pi[i],i)%pc[i];
c3+=returnthing;
LL xxxx,yyyy;
LL ni;
ex_gcd(b2*b3%pc[i],pc[i],xxxx,yyyy);
ni=(xxxx%pc[i]+pc[i])%pc[i];
LL rc=c1-c2-c3;
if(rc>=cc[i])f=0;
else f=b1*ni%pc[i]*power(pi[i],rc,pc[i])%pc[i];
now=(now+(p/pc[i])*pop[i]%p*f%p)%p;
}
return now%p;
}
void pyh(LL x){
LL tmps=x,sqr=sqrt(x);
for(LL i=2;i<=sqr;i++){
if(tmps%i==0){
pc[++pc[0]]=1;pi[++pi[0]]=i;
while(tmps%i==0){
cc[pc[0]]++;
pc[pc[0]]*=i;
tmps/=i;
}
}
}
if(tmps!=1){cc[++pc[0]]=1;pi[++pi[0]]=tmps;pc[pc[0]]=tmps;}
}
int main(){
scanf("%lld%lld%lld",&p,&n,&m);
for(LL i=1;i<=m;i++)scanf("%lld",&w[i]);
pyh(p);
for(LL i=1;i<=pc[0];i++){
tmp[i]=1;
for(LL j=1;j<pc[i];j++){
if(j%pi[i]==0){tott[i]++;continue;}
tmp[i]=tmp[i]*j%pc[i];
}
}
for(LL i=1;i<=pi[0];i++){
LL xxxx,yyyy;
ex_gcd(p/pc[i],pc[i],xxxx,yyyy);
pop[i]=(xxxx%pc[i]+pc[i])%pc[i];
}
for(LL i=1;i<=m;i++)s[i]=s[i-1]+w[i];
ans=1;
for(LL i=1;i<=m;i++)
ans=ans*work(n-s[i-1],w[i])%p;
if(ans==0)printf("Impossible\n");
else printf("%lld\n",ans);
return 0;
}