卢卡斯定理(Lucas)
证明如下:
结论:
卢卡斯定理的时间复杂度是plogN
代码如下:
#include<iostream>
using namespace std;
int n;
int p;
typedef long long ll;
int qmi(int a,int b)
{
int res = 1;
while(b)
{
if(b & 1)res = (ll)res * a % p;
a = (ll)a * a % p;
b >>= 1;
}
return res;
}
int C(int a,int b)
{
int res = 1;
for(int i = 1 , j = a; i <= b;i++,j--)
{
res = (ll)res * j % p;
res = (ll)res * qmi(i,p-2) % p;
}
return res;
}
ll Lucas(ll a,ll b)
{
if(a < p && b < p)return C(a,b);
else return (ll)C(a%p,b%p)* Lucas(a/p,b/p) % p;
}
int main()
{
cin>>n;
while(n--)
{
ll a, b;
cin>>a>>b>>p;
cout<<Lucas(a,b)<<endl;
}
return 0;
}
可以进一步优化,因为模数p所以可以先预处理p以内的数据(递推)
时间复杂度则将为 p + logN
每次都要重新预处理了p之前的数据
代码如下:
#include<iostream>
using namespace std;
int n;
int p;
typedef long long ll;
const int N = 1e5 + 7;
int fact[N],infact[N];
int qmi(int a,int b)
{
int res = 1;
while(b)
{
if(b & 1)res = (ll)res * a % p;
a = (ll)a * a % p;
b >>= 1;
}
return res;
}
void init()//预处理
{
fact[0] = infact[0] = 1;
for(int i = 1 ;i <= p ;i++)
{
fact[i] = (ll)fact[i-1] * i % p;
infact[i] = (ll)infact[i-1]*qmi(i,p-2) % p ;
}
}
ll Lucas(ll a,ll b)
{
if(a < p && b < p)return (ll)fact[a] * infact[b] % p * infact[a - b] % p ;
ll t = (ll)fact[a % p] * infact[b % p] % p * infact[a % p - b % p] % p;
return (ll) t* Lucas(a/p,b/p) % p;
}
int main()
{
cin>>n;
while(n--)
{
ll a, b;
cin>>a>>b>>p;
init();
cout<<Lucas(a,b)<<endl;
}
return 0;
}
{
ll a, b;
cin>>a>>b>>p;
init();
cout<<Lucas(a,b)<<endl;
}
return 0;
}