1 条题解
-
0
题意分析
本题主要围绕阶乘和整除的概念展开。给定两个非负整数
n
和m
,需要判断m
是否能整除n!
。其中阶乘函数n!
的定义为:当n = 0
时,n! = 1
;当n > 0
时,n! = n * (n - 1)!
。而若存在整数k
使得k * a = b
,则称a
能整除b
。程序的输入是若干行,每行包含两个小于2^31
的非负整数n
和m
,输出则是对于每一行输入,表明m
是否能整除n!
的信息。解题思路
本题的核心思路是对
m
进行质因数分解,然后计算n!
中每个质因数的个数,通过比较m
中每个质因数的个数和n!
中对应质因数的个数来判断m
是否能整除n!
。具体步骤如下:- 素数筛选:使用埃拉托斯特尼筛法的优化版本(线性筛)找出一定范围内(本题中为
N = 1000000
)的所有素数,并存储在数组p
中。 - 质因数分解:对于输入的
m
,将其分解为质因数及其对应的个数,存储在vector<factor>
类型的v
中。 - 计算
n!
中质因数的个数:对于v
中的每个质因数,计算n!
中该质因数的个数。可以利用公式:n!
中质因数p
的个数为n/p + n/p^2 + n/p^3 + ...
。 - 判断整除关系:比较
m
中每个质因数的个数和n!
中对应质因数的个数,如果m
中某个质因数的个数大于n!
中该质因数的个数,则m
不能整除n!
;否则,m
能整除n!
。
代码解释
//poj2649 #include<iostream> #include<vector> #include<cstring> using namespace std; const int N=1000000; bool prime[N+1]; long long p[N+1]; int k=0; // 线性筛法求素数 void getprime() { memset(prime,0,sizeof(prime)); prime[0]=1; prime[1]=1; for(int i=2;i<=N;i++) { if(!prime[i]) p[k++]=i; for(int j=0;j<k;j++) { if(p[j]*i>N) break; prime[p[j]*i]=1; if(i%p[j]==0) break; } } } // 定义结构体存储质因数及其个数 struct factor//a:素因子,k素因子的个数 { int a,k; }; vector<factor> v; // 对t分解质因子,结果存在v中 void getfen(int t) { v.clear(); for(int i=0;p[i]*p[i]<=t;i++) { if(t%p[i]==0) { factor a; a.a=p[i]; a.k=0; while(t%p[i]==0) { a.k++; t=t/p[i]; } v.push_back(a); } } if(t&&t!=1) { factor a; a.a=t; a.k=1; v.push_back(a); } } int main() { getprime(); int n,m; while(cin>>m>>n) { getfen(n); int flag=1; for(int i=0;i<v.size();i++) { int kk=0,l=v[i].a;//kk代表m中素因子v[i].a的个数 while(m/l) { kk+=m/l; l=l*v[i].a; } if(kk<v[i].k) { flag=0; break; } } if(m==0||n==0) flag=0; if(flag) cout<<n<<" divides "<<m<<"!"<<endl; else cout<<n<<" does not divide "<<m<<"!"<<endl; } }
- 素数筛选函数
getprime
:使用线性筛法找出2
到N
之间的所有素数,存储在数组p
中。prime
数组用于标记某个数是否为素数,k
记录素数的个数。 - 质因数分解函数
getfen
:对于输入的t
,将其分解为质因数及其对应的个数,存储在vector<factor>
类型的v
中。通过遍历素数数组p
,找出t
的所有质因数,并计算其个数。 - 主函数
main
:- 调用
getprime
函数生成素数表。 - 循环读取输入的
n
和m
。 - 调用
getfen
函数对m
进行质因数分解。 - 计算
n!
中每个质因数的个数,并与m
中对应质因数的个数进行比较。 - 根据比较结果输出
m
是否能整除n!
的信息。
- 调用
复杂度分析
- 时间复杂度:素数筛选的时间复杂度为 ,质因数分解的时间复杂度为 ,计算
n!
中质因数个数的时间复杂度为 ,因此总的时间复杂度为 ,其中T
为输入的行数。 - 空间复杂度:主要用于存储素数表和质因数分解结果,空间复杂度为 。
注意事项
- 边界条件:当
n = 0
或m = 0
时,需要特殊处理,直接判定m
不能整除n!
。 - 素数筛选范围:由于输入的
n
和m
小于2^31
,因此素数筛选的范围N
可以设置为一个合适的值,本题中设置为1000000
。 - 质因数分解:在对
m
进行质因数分解时,需要注意处理m
本身为素数的情况。
- 素数筛选:使用埃拉托斯特尼筛法的优化版本(线性筛)找出一定范围内(本题中为
- 1
信息
- ID
- 1649
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者