1)计算n!中有多少个质因子p (p<=n);
/**
1)计算n!中有多少个质因子p (p<=n);
*/
/**
#include <iostream>
using namespace std;
int cal(int n,int p); //计算n!有多少个因子p;
int main()
{
int n,m,p;
cin >> n >> p;
cout << cal(n,p) << endl;
cout << "Hello world!" << endl;
return 0;
}
int cal(int n,int p)
{
if(n<p)
return 0;
else
return n/p + cal(n/p,p);
}
*/
2)组合数的计算,C(n,m):从n个不同的元素中选出m个元素的方案数;
/**
2)组合数的计算,C(n,m):从n个不同的元素中选出m个元素的方案数;
*/
/**
#include <iostream>
using namespace std;
using ll=long long;
int cal(int n,int p); //计算n!有多少个因子p;
ll C(ll n, ll m); //计算n件物品里选m件物品的组合数
ll res[67][67]={0};
int main()
{
int n,m,p;
cout << "输入n,m,p\n";
cin >> n >> m >> p;
printf("输出%d!的因子%d 的个数:\n",n,p);
cout << cal(n,p) << endl;
printf("输入%d件物品里选%d件物品的组合数:\n",n,m);
cout << C(n,m) << endl;
cout << "Hello world!" << endl;
return 0;
}
int cal(int n,int p)
{
if(n<p)
return 0;
else
return n/p + cal(n/p,p);
}
1)根据定义式计算
//ll C(ll n,ll m) //计算n件物品里选m件物品的组合数,定义式
//{
// ll ans=1,temp;
// if(m<n-m) //temp存储较大的分母,m存储较小的分母
// {
// temp=m;
// m=n-m;
// }
// else
// temp=n-m;
// int i=1;
// for(;i<=n;++i)
// {
// ans*=i;
// if(i==temp)
// temp=ans;
// if(i==m)
// m=ans;
// }
// ans=ans/(temp*m);
// return ans;
//}
//
//
2)直接根据递推公式进行递归
//ll C(ll n,ll m) //C(n,m)=C(n-1,m)+C(n-1,m-1);
//{ //n件物品选m件可以堪看成在选择最后一件和不选最后一件的组合
// if(m==n) return 1;
// else if(m==1) return n; //但是这个递归函数的浪费非常大,
// else return C(n-1,m-1) + C(n-1,m); //有很多数之前都是算过的;
//}
3)计算C(n,m)%p;
//通过递推公式计算,支持n<=m<=1000,对p的大小和素性没有限制
/**
3)计算C(n,m)%p;
//通过递推公式计算,支持n<=m<=1000,对p的大小和素性没有限制
*/
/**
#include <iostream>
using namespace std;
using ll=long long;
const int x=1010,y=1010;
int CP(int n,int m,int p); //计算 C(n,m)%p;
ll ans[x][y]={0};
int main()
{
int n,m,p;
cout << "输入n,m,p\n";
cin >> n >> m >> p;
printf("输出C(%d,%d)%%%d的值:\n",n,m,p);
cout << CP(n,m,p) << endl;
cout << "Hello world!" << endl;
return 0;
}
1)计算 C(n,m)%p;递归调用
//int CP(int n,int m,int p) //计算 C(n,m)%p;递归调用
//{
// if(m==0||n==m) return 1;
// if(ans[n][m]!=0)
// return ans[n][m];
// return ans[n][m]=(CP(n-1,m,p)+CP(n-1,m-1,p))%p;
//}
//2)计算 C(n,m)%p,递推算出所有的值
int CP(int n,int m,int p) //计算 C(n,m)%p,递推算出所有的值
{
for(int i=0;i<=n;++i)
ans[i][0]=ans[i][i]=1;
for(int i=2;i<=n;++i)
for(int j=1;j<=i/2;++j)
{
ans[i][j]=(ans[i-1][j]+ans[i-1][j-1])%p;
ans[i][i-j]=ans[i][j]; //C(i,i-j)=C(i,j);
}
return ans[n][m];
}
*/
4)计算C(n,m)%p;
通过定义式计算:将C(n,m)进行质因子分解;支持n<=m<=1e6,对p的大小和素性没有限制
C(n,m)=n!/(m!*(n-m)!);将C(n,m)进行质因子分解,对遍历不超过n的质数Pi分别计算
n!,m!,(n-m)!的Pi的个数,个数分别为下,x,y,z.则C(n,m)中质因子Pi的个数为(x-y-z);
将结果累乘起来便可。
/**
4)计算C(n,m)%p;
通过定义式计算:将C(n,m)进行质因子分解;支持n<=m<=1e6,对p的大小和素性没有限制
C(n,m)=n!/(m!*(n-m)!);将C(n,m)进行质因子分解,对遍历不超过n的质数Pi分别计算
n!,m!,(n-m)!的Pi的个数,个数分别为下,x,y,z.则C(n,m)中质因子Pi的个数为(x-y-z);
将结果累乘起来便可。
*/
#include <iostream>
using namespace std;
using ll=long long;
const int maxn=1000001;
int cal(int n,int p); //计算n!有多少个因子p;
ll CP(int n,int m,int p); //计算 C(n,m)%p;
ll binaryPower(ll a,ll b,ll p); //计算a的b次方对p取模
void Find_prime(ll n);
int prime[maxn]={0};
bool is_prime[maxn]={0};
int main()
{
int n,m,p;
cout << "输入n,m,p\n";
cin >> n >> m >> p;
printf("输出C(%d,%d)%%%d的值:\n",n,m,p);
cout << CP(n,m,p) << endl;
cout << "Hello world!" << endl;
return 0;
}
int cal(int n,int p) //计算n!有多少个因子p;
{
if(n<p)
return 0;
else
return n/p + cal(n/p,p);
}
//1)利用递归计算a的b次方对p取模
ll binaryPower(ll a,ll b,ll p) //计算a的b次方对p取模
{ //利用递归
if(b==0) return 1;
if(b&1) //如果b是奇数,即最后一位二进制位是1
return a* binaryPower(a,b-1,p)%p;
else
{
ll mul=binaryPower(a,b/2,p);
return mul*mul%p;
}
}
2)利用快速幂(二分幂)计算a的b次方对p取模,迭代写法
//ll binaryPower(ll a,ll b,ll p) //计算a的b次方对p取模
//{ //利用快速幂(二分幂)
// ll ans=1;
// while(b>0)
// {
// if(b&1) //如果b的二进制末尾是1;
// ans=ans*a%p;
// a*=a%p; //令a平方
// b>>=1; //右移一位
// }
// return ans;
//}
void Find_prime(ll n) //找素数,将n以下的素数全存在数组里
{
int ans=0;
for(int i=2;i<=maxn;++i)
{
if(is_prime[i]==0)
prime[ans++]=i;
for(int j =i+i;j<=n;j+=i)
is_prime[j]=1;
}
}
ll CP(int n,int m,int p) //将C(n,m)进行质因子分解
{
Find_prime(n);
int ans=1;
for(int i=0;prime[i]<=n;++i)
{
int c=cal(n,prime[i])-cal(m,prime[i])-cal(n-m,prime[i]);
ans=ans*binaryPower(prime[i],c,p)%p;
}
return ans;
}