题目链接:https://www.luogu.com.cn/problem/P1463
首先,一看到题,就知道是道数论题,先口胡一个平方暴力,由于是道省选题,肯定过不了。
打表?估计要跑个十几年。。
先假设x的一个约数为a,a肯定小于等于根号下x,因为这样可以求出另一个约数x/a,再特判一下x是平方数的情况,于是我们两重循环,每重循环根号下x,时间复杂度O(n)。
正当思考是否准确时,一看数据范围,2e9,当场吐血。
O(logn)算法?快速幂?二分?你逗我?
O(1)算法?显然,这道题是求一个区间(1~n)中符合条件的最大值,没法加加减减得出答案。
显然,这题时间复杂度和n没有关系。
思考一个数的约数是怎么得来的。
设这个数为x,则x=p1^k1*p2^k2*...*pn^kn,约数个数为(k1+1)*(k2+1)*...*(kn+1),证明么,乘法原理,分步相乘。
这里的p数列都为素数且单调上升。
要让k数列尽可能的大,就要让p数列尽可能小,我们可以大胆猜想:p数列只取素数的前几项,至于前几项,实践出真知= =
然后呢?枚举k数列。。(其实这是一道搜索题,并不是数论题
好吧,放上代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int sum[20]={0,2,3,5,7,11,13,17,19,23,29,31,33};//素数表 4 long long n,ans,qwq; 5 void dfs(long long x,long long y,long long z){//x表示sum数组下标,y是当前数字,z是约数个数 6 if(z>qwq){ 7 qwq=z; 8 ans=y; 9 } 10 if(z==qwq&&ans>y)ans=y; 11 if(x>11)return; 12 for(long long i=1;i<=n;++i){ 13 if(y*sum[x]>n)return; 14 dfs(x+1,y*sum[x],z*(i+1)); 15 y*=sum[x]; 16 } 17 } 18 signed main(){ 19 cin>>n; 20 dfs(1,1,1); 21 cout<<ans<<endl; 22 return 0; 23 }
这种题刚上手肯定会一脸懵,做了一定的题之后肯定会有所进步。
码字不易,点个赞吧QwQ