任意一个大于1的正整数都能被表示成若干个素数的乘积且表示方法是唯一的;整理可以将相同素数的合并;可以得到
公式:n = P1^a1 * P2^a2 * …………* Pn^an(P1 < P2 < ……Pn);
用代码求一个数唯一分解后的式子我们可以先打素数表,在一直用质数去除它就行了。
代码:
void Prime()
{
cnt=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<=N;i++)
{
if(!vis[i])
prime[cnt++]=i;
for(int j=0;j
(例如,e={1,0,2,0,0,…}表示2^1*5^2=50)
至于唯一分解定理的用处:
1.可以证明a*b=gcd(a,b)*lcm*(a,b)(好像没啥用。。。。)
2.可以降低运算的数量级。大家都知道,数论的题一般规模很大,也许答案不会很大,但在求答案过程中乘着乘着就溢出了,所以产生了许多奇技淫巧来解决这种问题,唯一分解定理就是其中一个。特别是在有不能取余的除法时,可以通过质因子的约分得出答案。
例题:UVA10375
题意是求C(p,q)/C(r,s),保留五位小数,自然是用阶乘来求排列,再唯一分解一下,约个分,美滋滋。
代码:
#include
#include
#include
using namespace std;
const int N=10001;
int e[N],vis[N],prime[N];
int a,b,c,d,cnt;
void Prime()
{
cnt=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<=N;i++)
{
if(!vis[i])
prime[cnt++]=i;
for(int j=0;j>=1;
}
if(flag) return 1.0/res;
return res;
}
void adde(int num,int d)
{
for(int i=0;i
假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p),即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。(摘自百度百科)
//b/a=b*inv(a)(mod m)
int poww(int base,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*base%m;
base=base*base%m;
b>>=1;
}
return res;
}
void gcd(int a,int b,int& g,int& x,int &y)
{
if(!b) {g=a;x=1;y=0;}
else {gcd(b,a%b,g,y,x);y-=x*(a/b);}
}
int inv1()//线性递推逆元
{
inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=(m-m/i)*inv[m%i]%m;
}
int inv2()//扩展欧几里得求逆元
{
int x,y,g;
gcd(a,m,g,x,y);
return x;
}
int inv3()//费马小定理求逆元
{
return poww(a,m-2)%m;
}
int inv4(int a,int b)//取余除法通用法
{
//ans=a/b(mod m)
ans=a%(m*b)/b;
}
以上算法各有所长,也有各有各的缺点,如扩欧和费马小定理只能在m为质数才行。
#include
#include
#include
#define LL long long
using namespace std;
LL mod,n,m;
LL fac[10001];
void factor(){
fac[0]=1;
for(LL i=1ll;i<=mod;i++)
fac[i]=(fac[i-1]*i)%mod;
}
LL poww(LL base,LL b)
{
LL res=1ll;
while(b)
{
if(b&1) res=(res*base)%mod;
base=(base*base)%mod;
b>>=1;
}
return res;
}
LL C(LL x,LL y){
if(y>x) return 0;
return (fac[x]*poww(fac[y]*fac[x-y],mod-2))%mod;
}
LL lucas(LL x,LL y){
if(y==0) return 1ll;
return (C(x%mod,y%mod)*lucas(x/mod,y/mod))%mod;
}
int main()
{
//freopen("a.in","r",stdin);
scanf("%lld %lld %lld",&n,&m,&mod);
factor();
printf("%lld",lucas(n,m));
return 0;
}