1.花
( flower.cpp/c/pas)
【 问题描述】
商店里出售 n 种不同品种的花。为了装饰桌面,你打算买 m 支花回家。你觉得放两支一
样的花很难看,因此每种品种的花最多买 1 支。求总共有几种不同的买花的方案? 答案可能
很大,输出答案 mod p 的值。
【 输入格式】
一行 3 个整数 n, m, p, 意义如题所述。
【 输出格式】
一个整数,表示买花的方案数。
【输入输出样例 1】
flower.in | flower.out |
4 2 5 | 1 |
见选手目录下的 flower / flower1.in 与 flower / flower1.out
【输入输出样例 1 说明】
用数字 1,2,3,4 来表示花的种类的话,4 种花里买各不相同的 2 支的方案有(1,2)、(1,3)、
(1,4)、 (2,3)、 (2,4)、 (3,4), 共 6 种方案, 模 5 后余数是 1。
【输入输出样例 2】
见选手目录下的 flower / flower2.in 与 flower / flower2.out
【 数据范围】
对于 30%的数据, n,m≤10
对于 50%的数据, n,m≤1000
对于 80%的数据, 1≤m≤n≤50,000
对于 100%的数据, 1≤m≤n≤1,000,000, p≤1,000,000,000
解:100分:运用组合数公式:C(n,m)=n!/(m!*(n-m)!)
因为范围较大,所以进行质因数分解以约分,先打出质数表,最后直接寻找剩余质数并进行乘法取模即可;(必要时可使用快速幂与快速加)。
开 long #include<iostream>
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define man 1000010 #define sc(x) scanf("%lld",&x) #define mem(x) memset(x,0,sizeof(x)) #define ll long long using namespace std; ll used[man],prime[man],tot=0,aa=1; bool isp[man]; int n,m,p; inline void mkp(int x) { for(int i=2;i<=x;i++) { if(!isp[i]) { prime[++tot]=i; } for(int j=1;j<=tot&&i*prime[j]<=x;j++) { isp[i*prime[j]]=1; if(i%prime[j]==0) break; } } } void calc1(int x)//n { int ans=x; for(int i=1;i<=tot;i++) { if(ans%prime[i]==0) { int t=0; while(ans%prime[i]==0) { ans=ans/prime[i]; t++; } used[prime[i]]+=t; } if(!isp[ans]) { used[ans]++; ans=1; } if(ans==1) break; } } void calc2(int x)//m&(n-m) { int ans=x; for(int i=1;i<=tot;i++) { if(ans%prime[i]==0) { int t=0; while(ans%prime[i]==0) { ans=ans/prime[i]; t++; } used[prime[i]]-=t; } if(!isp[ans]) { used[ans]--; break; } if(ans==1) break; } } ll badd(ll a,ll b,ll c)//快速加 { ll ans=0,bas=a; while(b) { if(b&1) ans=(ans+bas)%p; bas=(bas+bas)%p; b>>=1; } return ans; } ll bpow(ll a,ll b,ll c)//快速幂 { int ans=1,bas=a; while(b) { if(b&1) ans=(ans*(bas%p))%p; bas=((bas%p)*(bas%p))%p; b>>=1; } return ans; } int main() { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); mem(prime);mem(used);mem(isp); sc(n);sc(m);sc(p); mkp(n); for(int i=2;i<=n;i++)//对n!质因数分解 calc1(i); for(int i=2;i<=m;i++)//对m!质因数分解 calc2(i); for(int i=2;i<=n-m;i++)//对(n-m)!质因数分解 calc2(i); for(int i=1;i<=tot;i++) { if(used[prime[i]]>0) { aa=badd(aa,bpow(prime[i],used[prime[i]],p),p); } } printf("%lld ",aa); return 0; }