牛客-n的约数(约数定理)

         n的约数

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

t次询问,每次给你一个数n,求在[1,n]内约数个数最多的数的约数个数

输入描述:

第一行一个正整数t
之后t行,每行一个正整数n

输出描述:

输出t行,每行一个整数,表示答案

 链接:https://www.nowcoder.com/acm/contest/82/A
来源:牛客网

示例1

输入

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;
}

你可能感兴趣的:(数论,牛客)