1.篩素數
const int maxn=100005;
int prime[maxn];
bool vis[maxn*10];
int cnt;
void getPrime()
{
int N=1000000;
int m=sqrt(N+0.5);
memset(vis,0,sizeof(vis));
for(int i=2;i<=m;i++) {
if(vis[i]==0) {
for(int j=i*i;j<=N;j+=i)
vis[j]=1;
}
}
cnt=0;
for(int i=2;i<=N;i++) {
if(!vis[i])
prime[cnt++]=i;
}
}
2.判斷一個數a是不是素數,int範圍內,可以篩出sqrt(a)以內的素數。
bool isPrime(int a)
{
if(a<2) return false;
for(int i=0;i<cnt;i++) {
if(prime[i]*prime[i]>a)
break;
if(a%prime[i]==0)
return false;
}
return true;
}
3。long long範圍內判素數,米勒羅賓
bool test (ll n,ll a,ll d)
{
if(n==2)
return true;
if(n==a)
return true;
if((n&1)==0)
return false;
while(!(d&1))
d=d>>1;
LL t=pow_mod(a,d,n);
while((d!=n-1)&&(t!=1)&&(t!=n-1))
{
t=(ll)t*t%n;
d=d<<1;
}
return (t==n-1||(d&1)==1);
}
bool isPrime(ll n)
{
if(n<2)
return false;
ll a[]= {2,3,5,7,61};
for(int i=0; i<=4; i++)
if(!test(n,a[i],n-1))
return false;
return true;
}
4.大組合數取模,n,m較小時預處理階乘和逆元就可以了,n,m在long long範圍,p<=1e5,p是素數,用lucas定理。
hdu3037 求C(n+m,m)%p
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#define fi first
#define se second
#define pii pair<int,int>
#define ll long long
#define inf 1<<30
#define eps 1e-8
using namespace std;
const int maxn=100005;
ll n,m,p;
ll jiech[maxn];
ll powMod(ll a,ll b,ll p)
{
if(b==0) return 1;
ll ans=powMod(a,b/2,p);
ans=ans*ans%p;
if(b&1)
ans=ans*a%p;
return ans;
}
ll lucas(ll n,ll m,ll p)
{
ll ret=1;
while(n&&m){
ll a=n%p,b=m%p;
if(a<b) return 0;
ret=(ret*jiech[a]*powMod(jiech[b]*jiech[a-b]%p,p-2,p))%p;
n/=p;
m/=p;
}
return ret;
}
int main()
{
int t;
scanf("%d",&t);
while(t--) {
scanf("%I64d%I64d%I64d",&n,&m,&p);
jiech[0]=1;
for(int i=1;i<=p;i++)
jiech[i]=jiech[i-1]*i%p;
printf("%I64d\n",lucas(n+m,m,p));
}
return 0;
}
5.n,m在long long 範圍,求C(n,m)%(p1*p2*p3*...*pk),pi是質數,pi<=1e5
用lucas求出所有C(n,m)%pi,中國剩餘定理求解。
hdu 5446
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#define fi first
#define se second
#define pii pair<int,int>
#define ll long long
#define inf 1<<30
#define eps 1e-8
using namespace std;
const int maxn=100005;
ll jiech[maxn];
ll inv[maxn];
ll p[10];
ll r[10];
ll n,m,k;
ll mod;
ll powMod(ll a,ll b,ll p)
{
if(b==0) return 1;
ll ans=powMod(a,b/2,p);
ans=ans*ans%p;
if(b&1)
ans=ans*a%p;
return ans;
}
ll lucas(ll n,ll m,ll p)
{
ll ret=1;
while(n&&m){
ll a=n%p,b=m%p;
if(a<b) return 0;
ret=(ret*jiech[a]*inv[b]%p*inv[a-b]%p)%p;
n/=p;
m/=p;
}
return ret;
}
void gcd(ll a, ll b, ll &d, ll &x, ll &y)
{
if (b == 0) {
d = a, x = 1, y = 0;
} else {
gcd(b, a%b, d, y, x);
y -= x * (a / b);
}
}
ll china(ll n, ll m[], ll a[])
{
ll aa = a[0];
ll mm = m[0];
for(int i=0;i<n;i++) {
ll sub = (a[i] - aa);
ll d, x, y;
gcd(mm, m[i], d, x, y);
if (sub % d) return -1;
ll new_m = m[i] / d;
new_m = (sub / d * x % new_m + new_m) % new_m;
aa = mm * new_m + aa;
mm = mm * m[i] / d;
}
aa = (aa + mm) % mm;
return aa;
}
int main()
{
int t;
scanf("%d",&t);
while(t--) {
scanf("%I64d%I64d%d",&n,&m,&k);
for(int i=0;i<k;i++) {
scanf("%I64d",&p[i]);
mod=p[i];
jiech[0]=1;
for(int j=1;j<mod;j++)
jiech[j]=jiech[j-1]*j%mod;
inv[mod-1]=powMod(jiech[mod-1],mod-2,mod);
for(int j=mod-2;j>=0;j--)
inv[j]=inv[j+1]*(j+1)%mod;
r[i]=lucas(n,m,mod);
}
printf("%I64d\n",china(k,p,r));
}
return 0;
}