【原创】高精度好题 Heaven Cow与God Bull

w h a t a 搞 人 心 态 高 精 度 好 题 \xcancel{what a 搞人心态}高精度好题 whata

Description

__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互质的数的个数。

Input

第一行是一个整数T,表示该测试点有T组数据。
接下来T行,每行一个整数n,意义如上所述。

Output

输出一共T行,每行一个整数m。
若对于某个n,有不止一个满足条件的m,则输出最小的m。

Sample Input

1

10

Sample Output

6

Data Constraint

对于10%的数据, n<=1000
对于30%的数据, n<=10^10
对于60%的数据, n<=10^2000
对于100%的数据,T<=100,n<=10^25000。

Analyse

没什么好分析的,随便打个表,发现最大值是 1 → 2 → 6 → 30 → 210 → 2310 → 30030 → 510510 → 9699690 ⋯ 1\to2\to 6\to30\to210\to2310\to30030\to510510\to9699690\cdots 126302102310300305105109699690(老子都能背出来了)

你也许可以和机智的我一样,尝试质因数分解;但是你绝对不能像*这就是祖安人打招呼的方式*的我一样,把 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。

Code

#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();
}

你可能感兴趣的:(#,题目,#,☠☠☠☠☠哼本人已死亡,#,☆☆☆★★嗯待沉吟片刻)