我也不知道为什么叫蚂蚁,,,
我也不知道原题是哪个。。。
但是既然是今天考试的题,还这么套路
就写一个博客来记录一下咯
题目:
求1-n约数个数最多的那个数
10%的数据 1
for(int i=1;i<=n;i++)
{
if(f[i]>sum){
sum=f[i];ans=i;
}
int bs=1;
while(bs*i<n){
bs++;
f[i*bs]++;
}
}
秒完之后一想,不对,数据这么大,应该打表!
然后打了一个表,试图找出其中的规律,最后放弃了
看着总觉得其中隐藏着什么不为人知的规律,可是,,,
不过同桌的frf却是天才地一个一个慢慢把答案打了出来(大概可以满分吧。。。。)
放弃了规律,忽然发现这是一道数学题
【注意,正文来了
/* 神奇的结论
int a[]=质数 ,k[]=指数
n= a[1]^k[1] * a[2]^k[2] *…..a[n]^k[n]
约数个数 t=(k[1]+1)(k[2]+1)…..*(k[n]+1)
枚举每一个质数指数 搜最大答案
转念一想,这虽然比暴力好了许多,不过大概会挂
这时我们就要有一些优化的思路:
这些思路的主旨就是在约数个数相同的情况下尽可能地让当前数小
比如:
1、第一种情况:6=2*3 10=2*5
这是一种约数不同的例子,所以我们枚举质数的时候要从小到大枚举
2、第二种情况:12=2^2*3 18=3^2*2
这时一种指数不同的例子,所以我们就可以推得较大的质数的指数一定小于较小的质数的指数
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
int p[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};
long long maxn=-1,num=-1;
void get(long long m,int f,int t,int pr)
{//f为当前质数的编号 ,当前指数<pr
//t为当前约数的个数
if(t>maxn||(t==maxn&&m<num))
num=m,maxn=t;
int j=0,nt;
long long i=m;
while(j<pr)
{
j++;
if(n/i<p[f])break;
nt=t*(j+1);
i=i*p[f];
if(i<=n) get(i,f+1,nt,j);
}
}
int main()
{
cin>>n;
get(1,1,1,30);
cout<<num;
}