Luogu P1463 [POI2002][HAOI2007]反素数【数论/dfs】By cellur925
题目描述
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?(N<=2000000000)
$Sol$
首先我们需要知道一个数约数的个数。这个是算术基本定理的推论,这里就不再赘述了,这儿稍微提了一句。
之后因为N在2e9内,所以它至多有10个质因子。
再次,我们要满足质因子从小到大的数量单调不增。为什么呢?当一个质因子比较小时,它就有更强的可塑性去贡献更多的因子。譬如出名要趁早以及当一个选手比你小还比你强你就没办法了这样的意思。
于是我们就可以直接采用$dfs$来维护最大的反素数。最大的反素数一定是相同约数中最小的。因为约数相同时,但是当他更大时,就更有可能出现比他小,约数还比他多的反素数。
代码中几个参量分别是当前质数下标,现在累乘的结果,当前质数出现的次数,上一个质数出现的次数,以及现在总约数个数。注意,当一个素数被完全用尽(开始搜下一质数时),才累计它的个数。
$Code$
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 typedef long long ll; 6 7 ll n,ans,num; 8 ll prime[50]={0,2,3,5,7,11,13,17,19,23,29,31,37,41}; 9 10 void dfs(int pos,ll mul,ll nowcnt,ll lastcnt,ll allcnt) 11 { 12 if(ans==allcnt*(nowcnt+1)&&mul<num) 13 num=mul; 14 if(allcnt*(nowcnt+1)>ans) 15 ans=allcnt*(nowcnt+1),num=mul; 16 if(nowcnt+1<=lastcnt&&mul*prime[pos]<=n) 17 dfs(pos,mul*prime[pos],nowcnt+1,lastcnt,allcnt); 18 for(int i=pos+1;i<=10;i++) 19 if(mul*prime[i]<=n) 20 dfs(i,mul*prime[i],1,nowcnt,allcnt*(nowcnt+1)); 21 } 22 23 int main() 24 { 25 scanf("%lld",&n); 26 dfs(1,1,0,50,1); 27 printf("%lld\n",num); 28 return 0; 29 }
$Others$
其实...本题还可以打表做。我们可以预先搞出所有的反素数,根据范围来得出答案。
但是...这个表最后我还是没完整地打出来(弱)。下面提供打部分表的思路。
1 /* 2 ---------------Sheet 1 -------------------- 3 #include<cstdio> 4 #include<algorithm> 5 #define maxn 500000000 6 7 using namespace std; 8 9 int ans=0; 10 short a[maxn];//技巧:用short省空间 11 12 int main() 13 { 14 freopen("1.out","w",stdout); 15 for(int i=1;i<=maxn-1;i++) 16 for(int j=i;j<=maxn;j+=i) 17 a[j]++; 18 19 for(int i=1;i<=maxn;i++) 20 if(a[i]>ans) 21 { 22 ans=a[i]; 23 printf("%d,",i); 24 } 25 printf("\n"); 26 printf("%d",ans); 27 return 0; 28 }*/ 29 /* 30 -----------Sheet 2--------------- 31 #include<cstdio> 32 #include<algorithm> 33 #define maxn 1000000001 34 #define maxpre 500000000 35 36 using namespace std; 37 38 int ans=1152; 39 short a[maxpre+1]; 40 41 int main() 42 { 43 freopen("1.out","w",stdout); 44 for(int i=1;i<=maxn-1;i++) 45 for(int j=(maxpre/i)*i+i;j<=maxn-1;j+=i) 46 a[j-maxpre]++; 47 48 for(int i=1;i<=maxpre;i++) 49 if(a[i]>ans) 50 { 51 ans=a[i]; 52 printf("%d,",i+500000000); 53 } 54 printf("\n"); 55 printf("%d",ans); 56 return 0; 57 }*/ 58 /*-----------Sheet3------------- 59 #include<cstdio> 60 #include<algorithm> 61 #define maxn 1500000001 62 #define maxpre 1000000000 63 64 using namespace std; 65 66 int ans=1344; 67 short a[(maxpre>>1)+1]; 68 69 int main() 70 { 71 freopen("1.out","w",stdout); 72 for(int i=1;i<=maxn-1;i++) 73 for(int j=(maxpre/i)*i+i;j<=maxn-1;j+=i) 74 a[j-maxpre]++; 75 76 for(int i=1;i<=maxpre;i++) 77 if(a[i]>ans) 78 { 79 ans=a[i]; 80 printf("%d,",i+maxpre); 81 } 82 printf("\n"); 83 printf("%d",ans); 84 return 0; 85 }*/ 86
独立意志与自由思想是必须争的,且须以生死力争。