AcWing 198. 反素数
考察:约数+推导
完全不会,fw本f
参考y总和lyd大佬的思路:
- 假设x为答案的话.当i<x,则g[i]<g[x]; 当i>x ,则g[i]<=g[x].因为x是最大的反质数.所以比x大的不允许有答案
- 假设x分解质因数的指数不呈递减式分布.那么后面大的数与前面小的数交换指数,可以得到一个更小且约数个数相同的答案,因此必呈递减分布
- 假设x的每个质因子只存在一次,那么最多只存在9个质因子,2*3*5*7*...*29后会溢出
- 质因子的指数最多为30.光是2^31次方就会大于N=2*10^9
- 这道题为什么递减补充说明一下:设答案为ans,如果存在数nums与ans的约数相等且nums>ans,那么ans就与最大反素数的定义相违背.
用过以上分析的内容,可以开始dfs.搜索每一个质因子的指数.不满足条件的return.写dfs一定要注意更新答案
注意: 如果直接写成tmp*mul会溢出造成答案错误,我们必须先将tmp压到不会溢出为止
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 typedef long long ll; 6 int prime[10] = {2,3,5,7,11,13,17,19,23,29};//假设有>29的质因子,则必有<29的质因子不能整除n 7 int n,tmp =1; 8 ll ans =1; 9 ll qsm(ll s,int k) 10 { 11 ll res = 1; 12 while(k) 13 { 14 if(k&1) res = res*s; 15 k>>=1; 16 s=(ll)s*s; 17 } 18 return res; 19 } 20 void dfs(ll tot,int k,ll res,int m,int sum) 21 { 22 if(sum>31||res>n||k==10) return; 23 if(tot==tmp&&res>ans) return; 24 if(tot>tmp) tmp = tot,ans = res; 25 if(tot==tmp&&res<ans) ans = res; 26 for(int i=m;i>=0;i--) 27 { 28 ll t = qsm(prime[k],i); 29 if(t>n) continue; 30 dfs(tot*(i+1),k+1,res*t,i,sum+i); 31 } 32 } 33 int main() 34 { 35 //freopen("in.txt","r",stdin); 36 scanf("%d",&n); 37 dfs(1,0,1,31,0); 38 printf("%lld\n",ans); 39 return 0; 40 }
2021.1.24 二刷,还是不会,卡在推导只有10种质因子那,然后完全没想到指数递减关系