1、先看一个简单的例子
输入不超过1000的正整数n,输出n的阶乘的精确结果。
样例输入:30
样例输出:265252859812191058636308480000000
#include<iostream>
using namespace std;
const int maxn = 3000;//用计算器算算,1000!约等于4*10^2567
int f[maxn];//用3000个元素的数组保存,f[0]对应个位,f[1]对应十位……
int main()//逆序存储是方便进位
{
int i, j, n;
cin>>n;
memset(f,0,sizeof(f));
f[0]=1;
for(i=2; i<=n; i++)
{//乘以i
int c=0;
for(j=0; j<maxn; j++)//每次乘以i,进位的处理,程序核心部分
{
int s = f[j]*i + c;
f[j] = s%10;
c = s/10;
}
}
for(j = maxn-1; j >= 0;j--) if(f[j]) break;//忽略前导 0
for(i = j; i >= 0; i--)
cout<<f[i];
cout<<endl;
return 0;
}
2、因子和阶乘
问题描述:输入正整数n(2<=n<=100),把n的阶乘分解乘素因子相乘的形式,从小到大输出各个素数(2,3,5,……)的
指数。例如825=3*5^2*11应表示成(0,1,2,0,1)表示分别有0、1、2、0、1个2、3、5、7、11。你的程序应忽略比最大因子更大的素数(否则末位会有很多个0)
样例输入:
5
53
样例输出:
5!= 3 1 1
53! = 49 23 12 8 4 4 3 2 2 1 1 1 1 1 1 1
#include<iostream>
using namespace std;
int is_prime(int n)//is_prime不能用于n特别大的情况,因为存在越界的可能
{
for(int i=2; i*i <= n; i++)
if(n % i ==0) return 0;
return 1;
}
//素数表
int prime[100], count = 0;
int main()
{
int i, n, p[100];//n和各个素数的指数
//构造素数表
for(i=2; i<=100; i++)
if(is_prime(i)) prime[count++] = i;
while(cin>>n)
{
cout<<n<<"! =";
memset(p, 0, sizeof(p));
int maxp=0;
for(i=1; i<=n; i++)
{
int m =i;//把i赋值给m,从而做除法时不会修改它的值
for(int j =0; j < count; j++)
while(m % prime[j] == 0)
{
m /= prime[j];//反复除以prime[j],并累加p[j]
p[j]++;
if(j>maxp) maxp=j;//更新最大因子的下标
}
}
for(i=0; i<=maxp; i++)//只循环到最大因子的下标
cout<<" "<<p[i];
cout<<endl;
}
return 0;
}
3、N的阶乘末尾有多少个0
分析:N! = K * 10^M,其中K不能被10整除,知N!末尾有M个0。考虑对N!进行质因子分解,N!=(2^X)*(3^Y)*(5^Z)…
由于10=2*5,于是M=min(X,Z),不难看出X>=Z(被2整除的数出现的频率比能被5整除的数出现的频率高的多),原问题
可简化为求因式分解中5的指数。
#include<iostream>
using namespace std;
int main()
{
int i, j, N, ret;
cin>>N;
/*另一种求Z的方法Z=[N/5]+[N/5^2]+[N/5^3]+…
ret=0;
while(N)
{
ret + =N/5;
N /= 5;
}
*****************************************************/
ret = 0;
for(i=1;i<=N; i++)
{
j=i;
while(j % 5 == 0)
{
ret++;
j /= 5;
}
}
cout<<ret<<endl;
return 0;
}
Z为N!中含有质因子5的个数,Z=[N/5]+[N/5^2]+[N/5^3]+…
4、求N!的二进制表示中最低位1的位置。
- 等价于N!中含有质因子2的个数加1(此结论由一个二进制数除以2的过程总结而得)
- N减去N的二进制表示中1的数目
假设N=11011,那么N!中质因子2的个数为[N/2]+[N/4]+[N/8]+[N/16]+…
即: 1101+110+11+1
=(1000+100+1)+(100+10)+(10+1)+1
=(1000+100+10+1)+(100+10+1)+1
=1111+111+1
=(10000-1)+(1000-1)+(10-1)+(1-1)
=11011-(N二进制表示中1的个数)