t次询问,每次给你一个数n,求在[1,n]内约数个数最多的数的约数个数
第一行一个正整数t 之后t行,每行一个正整数n
输出t行,每行一个整数,表示答案
链接:https://www.nowcoder.com/acm/contest/82/A
来源:牛客网
5 13 9 1 13 16
6 4 1 6 6
对于100%的数据,t <= 500 , 1 <= n <= 1000000000000000000
思路: 约数定理
约数定理:n可以分解质因数:n=p1^a1×p2^a2×p3^a3*…*pk^ak,
由约数定义可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1 ,共(a1+1)个;同理p2^a2的约数有(a2+1)个......pk^ak的约数有(ak+1)个。
故根据乘法原理:n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)。
约数和定理:
f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)
若n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1
实际上n的约数是在p1^a1、p2^a2、...、pk^ak每一个的约数中分别挑一个相乘得来,
可知共有(a₁+1)(a₂+1)(a₃+1)…(ak+1)种挑法,即约数的个数。
由乘法原理可知它们的和为
f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)
Code:
#include
using namespace std;
typedef long long LL;
const int a[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
int T;
LL n,ans;
void DFS(int k,LL sum,LL ni,int m);
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
ans=1;
cin>>n;
DFS(0,1,1,15);
cout<16) return;
ans=max(ans,sum);
for(int i=1;i<=m;++i)
if(ni<=n/a[k]){
ni*=a[k];
DFS(k+1,sum*(i+1),ni,i);
}else break;
}