__int64 ago,there’s a heaven cow called sjy…
A god bull named wzc fell in love with her…
As an OI & MOer,wzc gave sjy a quesiton…
给定一个整数n,求一个整数m,满足m<=n,并且m/phi(m)的值最大。
注:phi(m)代表m的欧拉函数,即不大于m且与m互质的数的个数。
第一行是一个整数T,表示该测试点有T组数据。
接下来T行,每行一个整数n,意义如上所述。
输出一共T行,每行一个整数m。
若对于某个n,有不止一个满足条件的m,则输出最小的m。
1
10
6
对于10%的数据, n<=1000
对于30%的数据, n<=10^10
对于60%的数据, n<=10^2000
对于100%的数据,T<=100,n<=10^25000。
没什么好分析的,随便打个表,发现最大值是 1 → 2 → 6 → 30 → 210 → 2310 → 30030 → 510510 → 9699690 ⋯ 1\to2\to 6\to30\to210\to2310\to30030\to510510\to9699690\cdots 1→2→6→30→210→2310→30030→510510→9699690⋯(老子都能背出来了)
你也许可以和机智的我一样,尝试质因数分解;但是你绝对不能像*这就是祖安人打招呼的方式*
的我一样,把 2310 2310 2310抄成 2130 2130 2130,最后看不出规律只得求助oeis。
于是规律就是质数的累乘, 2 × 3 × 5 × 7 × 11 × 13 × 17 × 19 × ⋯ 2\times3\times5\times7\times11\times13\times17\times19\times\cdots 2×3×5×7×11×13×17×19×⋯。
然后就是高精度的事情了。
首先你需要把素数表筛出来,然后直接乘起来。
T掉了!
我想想……
首先你需要把素数表筛出来,然后把所有数打表打出来,然后upper_bound-1。
A掉了!
很简单是吧?
压了十位才过,呀嘞呀嘞daze。
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll D=1e10;
const int MAXN=62030,MANA=60000,MAXL=25500,Z=10;
char s[25500];
bool vis[MAXN];
int T,cnt,pos,pri[MAXN];
struct NM$L
{
int len; ll arr[MAXL/Z];
inline void times(int x)
{
for(int i=1;i<=len;i++) arr[i]*=x;
for(int i=1;i<=len;i++) arr[i+1]+=arr[i]/D,arr[i]%=D;
while(arr[len+1]) len++,arr[len+1]+=arr[len]/D,arr[len]%=D;
}
inline void clear(){for(int i=1;i<=len;i++) arr[i]=0; len=0;}
inline bool operator < (const NM$L &s) const
{
if(len!=s.len) return len<s.len;
for(int i=len;i>=1;i--)
if(arr[i]!=s.arr[i]) return arr[i]<s.arr[i];
return 0;
}
inline bool operator <= (const NM$L &s) const
{
return !(s<*this);
}
inline void in()
{
scanf("%s",s+1),len=1;
int l=strlen(s+1);
for(int i=l;i>=1;i-=Z,len++)
for(int j=min(Z,i);j>=1;j--)
arr[len]=arr[len]*10+s[i-j+1]-'0';
len--;
}
inline void out()
{
printf("%lld",arr[len]);
for(int i=len-1;i>=1;i--) printf("%010lld",arr[i]);
puts("");
}
}n,las,ans[6000];
void shai()
{
for(int i=2;i<=MANA;i++)
{
if(!vis[i]) pri[++cnt]=i;
for(int j=1;j<=cnt && i*pri[j]<=MANA;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
ans[0].arr[ans[0].len=1]=1;
for(int i=1;i<=cnt;i++)
{
ans[i]=ans[i-1],ans[i].times(pri[i]);
if(ans[i].len>2500) {cnt=i; break;}
}
}
int main()
{
shai();
scanf("%d",&T);
while(T--) n.clear(),n.in(),las=ans[upper_bound(ans,ans+cnt+1,n)-ans-1],las.out();
}