ABC-400-E - Ringo's Favorite Numbers 3 · znzryb
## 思路讲解
::: 约数个数定理

:::
[ABC-383-D - 9 Divisors ](/2025/02/02/20250202-b24822c7)
其实这个约数个数定理是显然的
你想p1的指数有$0~e_1$也就是$e_1+1$种选择,同理,每种都有$e_k+1$种选择
那么根据乘法原理,约束个数也就是 $d(n)=(e_1+1)(e_2+1)…(e_k+1)$
当然喽,只有素因子可以这么玩,非素因子这么玩可能会有重复
---
当然这道题目关键点不在上面。
$N=p_1^{e_1}p_2^{e_2}$ 由题意可得,e1为偶数,e2也为偶数。所以其实400数要求是**完全平方数**,而且是只由两个素因子构成。那么其实也就是要求平方数由两个素因子组成。
哈哈,其实这种也是有点套路,一般来说这种都是直接枚举素因子的
我们用埃氏筛筛出所有1e6以内的素数,存储在primes中。然后就枚举就完了。
::: 枚举代码
```cpp
for(int i=0;i<primes.size();++i){
ll p=primes[i];
for(ll j=p;j<=MAXN-10;j*=p){
for(int k=i+1;k<primes.size();++k){
ll pk=primes[k];
if(pk*j>MAXN-10) break;
for(ll p_k=pk;p_k<=MAXN-10;p_k*=pk){
if(p_k*j>MAXN-10) break;
fitNum.pb(p_k*j);
}
}
}
}
```
:::
## AC代码
::: 源代码
```cpp
// Problem: E - Ringo's Favorite Numbers 3
// Contest: AtCoder - AtCoder Beginner Contest 400
// URL: https://atcoder.jp/contests/abc400/tasks/abc400_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// by znzryb
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define fi first
#define se second
#define pb push_back
#define SZ(a) ((int) a.size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<ll,ll> pll;
typedef array<ll,3> arr;
typedef double DB;
typedef pair<DB,DB> pdd;
typedef pair<ll,bool> plb;
constexpr ll MAXN=static_cast<ll>(1e6)+10,INF=static_cast<ll>(5e18)+3;
ll N,M,T;
bool isPrime[MAXN];
vector<ll> primes;
vector<ll> fitNum; // 符合含有两个素因子的数
inline void solve(){
cin>>N;
ll sqN=sqrtl(N);
// #ifdef LOCAL
// cerr << sqN << '\n';
// #endif
ll sqAns=*prev(upper_bound(all(fitNum),sqN));
cout<<sqAns*sqAns<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// 先进行预处理
for(int i=2;i<=MAXN-10;++i){
isPrime[i]=true;
}
// 埃氏筛
// 假设MAXN-10以内有一个合数没有标记,那么他必然有一个小于sqrt(MAXN-10)的因子
for(int i=2;i*i<=MAXN-10;++i){
if(isPrime[i]){
for(int j=2*i;j<=MAXN-10;j+=i){
isPrime[j]=false;
}
}
}
for(int i=2;i<=MAXN-10;++i){
if(isPrime[i]) primes.pb(i);
}
for(int i=0;i<primes.size();++i){
ll p=primes[i];
for(ll j=p;j<=MAXN-10;j*=p){
for(int k=i+1;k<primes.size();++k){
ll pk=primes[k];
if(pk*j>MAXN-10) break;
for(ll p_k=pk;p_k<=MAXN-10;p_k*=pk){
if(p_k*j>MAXN-10) break;
fitNum.pb(p_k*j);
}
}
}
}
sort(all(fitNum));
// #ifdef LOCAL
// for(int i=0;i<=10;++i){
// cerr<<fitNum[i]<<" ";
// }
// cerr<<"\n";
// #endif
cin>>T;
while(T--){
solve();
}
// solve();
return 0;
}
/*
AC
https://atcoder.jp/contests/abc400/submissions/64639281
*/
```
:::
## 心路历程(WA,TLE,MLE……)
这个ll是非常需要的,写成int以后就TLE了,可能是因为溢出了。
```cpp
for(int i=0;i<primes.size();++i){
ll p=primes[i];
for(ll j=p;j<=MAXN-10;j*=p){
for(int k=i+1;k<primes.size();++k){
ll pk=primes[k];
if(pk*j>MAXN-10) break;
for(ll p_k=pk;p_k<=MAXN-10;p_k*=pk){
if(p_k*j>MAXN-10) break;
fitNum.pb(p_k*j);
}
}
}
}
```