这是一道CTSC水题
题目描述
一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。
输入输出格式
输入格式:
输入的第一行包含一个正整数P,表示模;
第二行包含两个整整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;
以下m行每行仅包含一个正整数wi,表示小E要送给第i个人的礼物数量。
输出格式:
若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模P后的方案数。
输入输出样例
输入样例#1: 复制
100 4 2 1 2
输出样例#1: 复制
12
输入样例#2: 复制
100 2 2 1 2
输出样例#2: 复制
Impossible
说明
【样例说明】
下面是对样例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=p1^c1 * p2^c2 * p3^c3 * … *pt ^ ct,pi为质数。
对于15%的数据,n≤15,m≤5,pi^ci≤10^5;
在剩下的85%数据中,约有60%的数据满足t≤2,ci=1,pi≤10^5,约有30%的数据满足pi≤200。
对于100%的数据,1≤n≤10^9,1≤m≤5,1≤pi^ci≤10^5,1≤P≤10^9。
这个思路真的是很水很水很水
思路学过组合数的都能想出来,这道题主要就是要会exlucas,可以看我的博客点这里
唯一注意的就是不要手残,不写函数名,用一个括号括上几个变量,因为这样不会CE但是得调试半天(我真是瞎了QAQ)
上代码!
1 #include<cstdio> 2 #include<algorithm> 3 #define lt long long 4 #define rt register lt 5 #define il inline 6 using namespace std; 7 lt p,n,m,w,tot,ans=1; 8 namespace misaki 9 { 10 il lt gcd(lt a,lt b){return b?gcd(b,a%b):a;} 11 il lt lcm(lt a,lt b){return a/gcd(a,b)*b;} 12 il lt ksc(lt a,lt b,lt mod) 13 { 14 if(a==0||b==0)return 0; 15 lt fina=0,kk=1; 16 if(a<0)a=-a,kk=-kk; 17 if(b<0)b=-b,kk=-kk; 18 while(b) 19 { 20 if(b%2)fina=(fina+a)%mod; 21 b>>=1,a=(a+a)%mod; 22 } 23 return fina%mod*kk; 24 } 25 il lt ksm(lt a,lt k,lt mod) 26 { 27 if(!k)return 1; 28 lt fina=1; 29 while(k) 30 { 31 if(k%2)fina=ksc(fina,a,mod); 32 k>>=1,a=(a*a)%mod; 33 } 34 return fina%mod; 35 } 36 il void ex_gcd(lt a,lt b,lt &x,lt &y) 37 { 38 if(!b)x=1,y=0; 39 else 40 { 41 ex_gcd(b,a%b,x,y); 42 lt tt=x;x=y,y=tt-a/b*x; 43 } 44 } 45 il lt exgcd(lt a,lt b,lt c) 46 { 47 lt gc=gcd(a,b),x=0,y=0; 48 if(c%gc){ printf("aaa");return -1;} 49 a/gc,b/=gc,c/=gc; 50 ex_gcd(a,b,x,y); 51 return (x*c%b+b)%b; 52 } 53 il lt inv(lt a,lt p) 54 { 55 if(!a)return 0; 56 return exgcd(a,p,1); 57 } 58 } 59 namespace lucas 60 { 61 using namespace misaki; 62 il lt fac(const lt n,const lt pi,const lt pk)//n!%p^k 63 { 64 if(n==1||n==0)return 1; 65 lt ans=1; 66 for(rt i=2;i<pk;i++) 67 if(i%pi)ans=ans*i%pk; 68 ans=ksm(ans,n/pk,pk); 69 for(rt i=2;i<=n%pk;i++) 70 if(i%pi)ans=ans*i%pk; 71 return ksc(ans,fac(n/pi,pi,pk),pk); 72 } 73 il lt C(const lt n,const lt m,const lt pi,const lt pk)//C(n,m)%p^k 74 { 75 lt up=fac(n,pi,pk),dl=fac(m,pi,pk),dr=fac(n-m,pi,pk),sum=0; 76 for(rt i=n;i;i/=pi)sum+=i/pi; 77 for(rt i=m;i;i/=pi)sum-=i/pi; 78 for(rt i=n-m;i;i/=pi)sum-=i/pi; 79 return up*inv(dl,pk)%pk*inv(dr,pk)%pk*ksm(pi,sum,pk)%pk; 80 } 81 il lt exlucas(const lt n,const lt m,const lt P) 82 { 83 lt tt=P,ans=0; 84 for(rt i=2;i<=tt;i++) 85 if(tt%i==0) 86 { 87 lt pi=i,pk=1; 88 while(!(tt%i))tt/=i,pk*=i; 89 ans=(ans+C(n,m,pi,pk)*(P/pk)%P*inv(P/pk,pk)%P)%P; 90 } 91 return ans%P; 92 } 93 } 94 int main() 95 { 96 scanf("%lld%lld%lld",&p,&n,&m);bool fl=0; 97 for(rt i=1;i<=m;i++) 98 { 99 scanf("%lld",&w); 100 if(n<w){fl=1;break;}tot+=w,ans=(ans*lucas::exlucas(n,w,p))%p,n-=w; 101 } 102 if(fl)puts("Impossible"); 103 else printf("%lld",ans); 104 return 0; 105 }
原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10104831.html