AcWing 198. 反素数

原题链接

考察:约数+推导

完全不会,fw本f

参考y总和lyd大佬的思路:

  1. 假设x为答案的话.当i<x,则g[i]<g[x]; 当i>x ,则g[i]<=g[x].因为x是最大的反质数.所以比x大的不允许有答案
  2. 假设x分解质因数的指数不呈递减式分布.那么后面大的数与前面小的数交换指数,可以得到一个更小且约数个数相同的答案,因此必呈递减分布
  3. 假设x的每个质因子只存在一次,那么最多只存在9个质因子,2*3*5*7*...*29后会溢出
  4. 质因子的指数最多为30.光是2^31次方就会大于N=2*10^9
  5. 这道题为什么递减补充说明一下:设答案为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种质因子那,然后完全没想到指数递减关系

posted @ 2021-01-16 11:10  acmloser  阅读(59)  评论(0编辑  收藏  举报