一. 唯一分解定理
A=p1^a * p2^b * p3^c(其中p1,p2,p3为A的质因子)
1. A的因子数:num=(a+1)*(b+1) * (c+1)*...;
2 . A的因子和:
sum(c)=p1^0 + p1^1 + ... p1^a+;
sum(d)=p2^0 + p2^1 + ...+ p2^b;
sum(e)=p3^0 + p3^1 +...+ p3^c;
..............
sum=sum(b) * sum(d) * sum(e)*...;
二. 除法取模:
1.(x/d)%k =x%(d*k)/d (x/d!=0)(等比数列求和中快速幂模)
例:http://acm.hdu.edu.cn/showproblem.php?pid=4990
2. (x/d)%k=(x* d1) %k (d1为d的逆元)
三.逆元求法:
逆元定义:ax=1 (mod m)---->ax+my=1 —>exgcd(a,m)
1. 扩展欧几里得算法:
ax+by=gcd(a,b)=1, x为a的逆元 y为b的逆元;
int exgcd(int a,int b,int &x,int &y)
{
int d=a;
if(d==0)
{
x=1;
y=0;
}
else
{
d=exgcd(b,a%b,y,x);
y-=a/b*x;
}
return d;
}
//求ax=1 (mod m)
int get_number(int a,int mod)
{
int x,y;
int temp=exgcd(a,mod,x,y);//另ax+by=1 中的a=a b=mod;;
if(temp!=1)
{
printf("-1\n");//不存在
}
else printf("%d\n",x);//a的逆元为x;
}
2.费马小定理求逆元:
对任意的P,A互质,都有A的(P-1)次方取模与P等于1,公式表示为:
A^p-1≡1(mod P)
A*X≡1(mod p) 两式得出A的逆元X=A^p-2(快速幂计算)
注:此时满足P,A互质(p为质数常用)
四:扩展欧几里得解线性同余方程
ax=b (mod m)------>ax-my=b 令d=exgcd(a,m,x,y)
则 x=x0 * b/d 为方程一解 mod=m/d (解集:x=x0*b/d+k*mod);
非负最小解:x=(x%mod+mod)%mod(如果x==0 x+=mod);
例:http://poj.org/problem?id=2115
另外:若方程为ax+by=c 时 同上
例:http://poj.org/problem?id=1061
五:求n!中因子个数
结合唯一分解定理 M=(e1+1)*(e2+1)*...*(en+1)
以及公式 ei=[N/pi^1]+ [N/pi^2]+ …… + [N/pi^n] 其中pi为n以内的素数,ei当n!在
分子为正 分母为负
例:http://poj.org/problem?id=2992
六:欧拉函数的实现:
void euler(int n)//求n的欧拉函数值
{
int ans=n,temp=n;
for(int i=2;i*i<=temp;i++)
{
if(n%i==0)//i为素数 且是n的因子
{
ans=ans-ans/i;
while(n%i==0) n/=i;
}
}
if(n>1) ans=ans-ans/n;
return ans;
}
//欧拉函数的筛选法
int phi[maxn+10];
void get_phi()
{
for(int i=0;i<=maxn;i++) phi[i]=i;
for(int i=2;i<=maxn;i++)
{
if(phi[i]==i)
{
for(int j=i;j<=maxn;j+=i)
{
phi[j]=phi[j]/i*(i-1);
}
}
}
}
七:卢卡斯定理
卢卡斯定理主要用来求组合 C(n,m) %p
费马小定理实现(p为素数):
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll mulit(ll a,ll b,ll m){
ll ans=0;
while(b){
if(b&1) ans=(ans+a)%m;
a=(a<<1)%m;
b>>=1;
}
return ans;
}
ll quick_mod(ll a,ll b,ll m){
ll ans=1;
while(b){
if(b&1){
ans=mulit(ans,a,m);
}
a=mulit(a,a,m);
b>>=1;
}
return ans;
}
ll comp(ll a,ll b,ll m){
if(a<b) return 0;
if(a==b) return 1;
if(b>a-b) b=a-b;
ll ans=1,ca=1,cb=1;
for(int i=0;i<b;i++){
ca=ca*(a-i)%m;
cb=cb*(b-i)%m;
}
ans=ca*quick_mod(cb,m-2,m)%m;
return ans;
}
ll lucas(ll a,ll b,ll m){
ll ans=1;
while(a&&b){
ans=(ans*comp(a%m,b%m,m))%m;
a/=m;
b/=m;
}
return ans;
}
int main()
{
ll a,b,m;
while(cin>>a>>b>>m){
cout<<lucas(a,b,m)<<endl;
}
return 0;
}
扩展欧几里得实现:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll& x,ll& y){
if(a%b==0){
x=0,y=1;
return b;
}
ll r,tx,ty;
r=exgcd(b,a%b,tx,ty);
x=ty;
y=tx-a/b*ty;
}
ll comp(ll a,ll b,ll m){
if(a<b) return 0;
if(a==b) return 1;
if(b>a-b) b=a-b;
ll ans=1,ca=1,cb=1;
for(int i=0;i<b;i++){
ca=ca*(a-i)%m;
cb=cb*(b-i)%m;
}
ll x,y;
exgcd(cb,m,x,y);
x=(x%m+m)%m;
ans=ca*x%m;
return ans;
}
ll lucas(ll a,ll b,ll m){
ll ans=1;
while(a&&b){
ans=(ans*comp(a%m,b%m,m))%m;
a/=m;
b/=m;
}
return ans;
}
int main()
{
ll a,b,m;
int n;
cin>>n;
while(n--){
cin>>a>>b>>m;
cout<<lucas(a+b,b,m)<<endl;
}
return 0;
}