--- title: "反素数" created: 2025-11-28 tags: - 算法 --- # 反素数 ## 题目 [反素数](https://www.acwing.com/problem/content/200/) ![[image-4bd6550e.png]] ## 思路分析 分析题意的时候 看着打的表有点想用刚才刚整理的倍增思想的冲动 就试了一下 好像可以 ![[image-6fb3e5ee.png]] 从1做到n 把每个数的倍数的记录数都++(实际含义是 这些数都包含这个因子) 结束后 g[i]记录的就是每个数的约数的数量 然后就是找一个单调递增的顶峰 贪心想一下 好像可以直接找最大值 如果它最大 就一定比左边的所有的都大 对于左边来说它一定是答案 对于右边来说 右边某个数的左边是这个最大值 那么一定不是单增 那右边一定没有答案 好像是可以的 那就用一个max维护就好了 ```cpp const int N=2e9+10; int g[N]; //开不了 太大了 开到1e6+10能过6个 //改成vector版本 #include using namespace std; typedef long long LL; int main() { int n; cin>>n; vector g(n); for(int i=1;i<=n;i++){ for(int j=i;j<=n;j+=i){ g[j]++; } } int maxv=-1,idx=1; for(int i=1;i<=n;i++){ if(g[i]>maxv){ maxv=g[i]; idx=i; } } cout< #include // #include由于这个题目的读入量很小,所以我们完全可以用cin来读 #include using namespace std; int primes[9]={2,3,5,7,11,13,17,19,23};//primes的话一共是有9个对吧 typedef long long LL;//当然这里要加一个long long 啊 int maxd;//比方说我们的约数个数可以记为我们的maxd int number;//然后数本身的话可以记成number int n;//然后还有一个n对吧,这是我们读入的这个数 void dfs(int u,int last,int p,int s)//好,那我们dfs一下,上一个的次数,上一个数,以及我们的约数个数 { //好,然后如果我们当前的约数个数是大于我们的最大约数个数了 //或者是等于等于最大约数个数并且p小于number的话 if(s>maxd||s==maxd&&pn)//那每次都先算一下我们这个这个,p乘上一个我们当前的质数,看一下是不是已经大于n了 break;//大于n的话那就直接break就可以了对吧 //好,然后否则的的话,咱们就让p就乘上一个primes[u] p*=primes[u]; //好然后再dfs下一次 dfs(u+1,i,p,s*(i+1));//u+1,然后是这个i,对吧,p,还有这个s*(i+1); //好,然后我们来调试一下 } } int main() { cin>>n; /*字 幕 开 始*/ //首先dfs一遍 //那么dfs里面是有几个参数呢? //第一个是我们枚举到第几个质数了,第0个对吧,从第0个开始枚举 //然后下一个的话是我们的次数最大是多少对吧,那我们刚刚说了次数最大是30对吧,当前最大次数是30 //然后我们这个数本身乘积是多少?这个乘积本身是1对吧 //好,然后...(y总摸了摸鼻子和嘴唇继续说)呃...下一个,下一个应该是约数个数对吧,约数个数的话最开始是1对吧 //因为我们约数个数是通过公式来算的,每次都要乘上一个数,所以在没乘之前应该是1 dfs(0,30,1,1); //哦,忘记输出了咱们,咱们要把这个答案输出 cout<